P
Peter Judge
Guest
This is because the http client uses the built-in JsonObject class to build the payload and those classes only support objects and arrays, not the primitive types (strings, numbers, booleans and null) per www.ietf.org/.../rfc4627.txt . Please log a bug with TS for this. I can offer a workaround that requires some changes to your code (based on the 11.6 code) in the interim. First, create a body writer that does what you need. The http client uses pluggable modules for writing various content types. An example called MyJsonBodyWriter appears below. This version can support null and the primitive values in addition to objects and arrays. Support for logical and numeric values is via the ByteBucket/Memptr types and there's no validation on whether those are valid JSON, so YMMV. To pass a null value, create a ByteBucket with a string of NULL ( myBB
utString('NULL') should do the trick ). Second, register your new writer as the handler for application/json . You need to do this once per session, before you make your requests. using OpenEdge.Net.HTTP.Filter.Writer.BodyWriterRegistry. BodyWriterRegistry:Registry: Put ( 'application/json' :u, get-class (MyJsonBodyWriter)). Third, change how you build the request, in order to override the default Content-Type inference def var s as OpenEdge.Core.String. def var myReq as IHttpRequest. s = new String ( 'bar' ). myReq = RequestBuilder
ost(URI
arse( ' http://httpbin.org/post' ), // override the default content-type inferred from the object's type s, 'application/json' ) : Request . You can use String, JsonObject, JsonArray, Memptr and ByeBucket instances for the payloads in this example. Things should now work as expected. JSON Writer class. block-level on error undo , throw . using OpenEdge.Core.ByteBucket. using OpenEdge.Core.String. using OpenEdge.Net.HTTP.Filter.Payload.MessageWriter. using Progress.Json.ObjectModel.JsonConstruct. using Progress.Lang.AppError. using Progress.Lang.Object. using OpenEdge.Core.Memptr. class MyJsonBodyWriter inherits MessageWriter: constructor public MyJsonBodyWriter(): super ( get-class (ByteBucket)). end constructor . method override public void Open (): if not valid-object ( this-object :Entity) then assign this-object :Entity = ByteBucket:Instance(). super : Open (). end method . method override public int64 Write ( input poData as Object ): define variable mJson as memptr no-undo . define variable iBytesWritten as int64 no-undo . case true : when not valid-object (poData) then do : cast ( this-object :Entity, ByteBucket): Clear (). cast ( this-object :Entity, ByteBucket)
utString( "null" :u). assign iBytesWritten = 4 . end . // nulls/unknowns when type-of (poData, Memptr ) then do : cast ( this-object :Entity, ByteBucket): Clear (). cast ( this-object :Entity, ByteBucket)
utBytes( cast (poData, Memptr )). assign iBytesWritten = cast (poData, Memptr ): Size . end . // bytes: Memptr when type-of (poData, ByteBucket) then do : cast ( this-object :Entity, ByteBucket): Clear (). cast ( this-object :Entity, ByteBucket)
utBytes( cast (poData, ByteBucket)). assign iBytesWritten = cast (poData, ByteBucket): Size . end . // bytes: Bucket when type-of (poData, String ) then do : cast ( this-object :Entity, ByteBucket): Clear (). cast ( this-object :Entity, ByteBucket)
utString( substitute ( "~"&1~"" :u, cast (poData, String ): Value )). assign iBytesWritten = cast (poData, String ): size + 2 . end . // String when type-of (poData, JsonConstruct) then do on error undo , throw : cast ( this-object :Entity, ByteBucket): Clear (). cast (poData, JsonConstruct): Write (mJson). /* Add the JSON to the message body's bytebucket */ assign iBytesWritten = get-size (mJson). cast ( this-object :Entity, ByteBucket)
utBytes( get-pointer-value (mJson), iBytesWritten). finally : set-size (mJson) = 0 . end finally . end . // JSON otherwise return error new AppError( substitute ( 'Unsupported object type: &1' , poData:GetClass():TypeName) , 0 ). end case . return iBytesWritten. end method . end class .
Continue reading...
Continue reading...