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:PutString('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').
// 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):PutString("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):PutBytes(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):PutBytes(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):PutString(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):PutBytes(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.