SuperObject cannot handle null string
Asked Answered
L

1

3

Some JSON serializers return null for an empty string datafield, e.g.

{
 "searchtext": null,
 "moretext": "contains something",
 "bookdate": 1377468000000,
 "empid": 12345,
 "listtype": 1
}

I'm using SuperObject to create a ISuperObject:

var
  FJSONRequest: ISuperObject; 
then
  FJSONRequest := SO(Request.Content);   // Webservice request

This returns an object with a string containing the text 'null'.

Obviously this is because SuperObject does not care about the quotes ("searchtext": a gives the same results as "searchtext": "a").

Before I dive into the 980-line tokenizer routine, does any one have a solution?

I'm thinking along the lines (either/or):

  • leave the null datafield out of the JSON object

  • return an empty string

If all else fails I could still do

FJSONRequest := SO(StringReplace(Request.Content,': null,',':,',[rfReplaceAll]));  

because I only need to handle requests coming from an app from one of our developers, but that's not foolproof.
(No, he cannot suppress the null because there's a bug in the way Mono handles his datacontract.)

BTW I'm experiencing exactly the behaviour mentioned here, but in another part of the SuperObject code, so that workaround does not do the job.

Longspur answered 26/8, 2013 at 13:25 Comment(4)
null is not the same thing as an empty string. It has a completely different meaning. Your StringReplace won't work. Think what it does to the text annulled.Illuminator
Set my stringReplace() tighter, but indeed not foolproof.Longspur
The bug you mention appears to have been fixed more than a year before it was reported. And tokenization of null seems correct, too, inasmuch as Super Object correctly parses valid JSON and rejects invalid JSON at all. Look for handling of the tsNull state in TSuperObject.ParseEx. Are you sure you're using a recent version of the code?Rhigolene
@Rob: Bummer. The official 1.2.4 ZIP file in the download section code.google.com/p/superobject/downloads/list dates from 2010, but the individual files in code.google.com/p/superobject/source/browse have updates up until Oct 2012. Thanks, I'll do file comparisons and report back.Longspur
L
3

The official 1.2.4 ZIP file in the download section http://code.google.com/p/superobject/downloads/list dates from 2010, but the individual files in http://code.google.com/p/superobject/source/browse have updates up until Oct 2012.

If you go to that last URL and click on Download zip you can retrieve them.

These updated files let you use the special case null.

The code is still 'forgiving' if you omit the quotes around the string value:

{
 "bookdate": 1377554400000,
 "searchtext": a,
 "listtype": 1
}

but it now handles the special case

{
 "bookdate": 1377554400000,
 "searchtext": null,
 "listtype": 1
}

as if it was

{
 "bookdate": 1377554400000,
 "searchtext": ,
 "listtype": 1
}

or

{
 "bookdate": 1377554400000,
 "listtype": 1
}

[Do not accidentally type nil or NULL]

This release supports up until VER230 (Delphi XE2) [Note that the 'official' 1.2.4 did not even compile on more recent Delphi versions], so for later versions of Delphi you'll have to patch the compiler directives.

It also fixes the following:

  • When an floating point value happened to have an exact integer value, the JSON would have a trailing period:

    { "floatingpointvalue": 4. }

    This is now fixed:

    { "floatingpointvalue": 4 }

  • Errors in datetime conversions happening around the switch to daylight savings time in leapyears - yes, obscure.
    There was an error in the code section surrounded by {$IFDEF WINDOWSNT_COMPATIBILITY}

Note that this is still defined by default, I suggest you disable the define , e.g. with {.$IFDEF WINDOWSNT_COMPATIBILITY} [who needs to run on Windows NT nowadays?], which lets the OS handle datetime conversions:

{$ELSE}
function TzSpecificLocalTimeToSystemTime(
  lpTimeZoneInformation: PTimeZoneInformation;
  lpLocalTime, lpUniversalTime: PSystemTime): BOOL; stdcall; external 'kernel32.dll';

function SystemTimeToTzSpecificLocalTime(
  lpTimeZoneInformation: PTimeZoneInformation;
  lpUniversalTime, lpLocalTime: PSystemTime): BOOL; stdcall; external 'kernel32.dll';
{$ENDIF}
Longspur answered 27/8, 2013 at 9:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.