Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SuperObject - Parsing data from a fieldname with a "." literal

I recently came up against a wall when parsing JSON. You see, when working with the CloudFlare Client Interface API, i wanted to lookup the "threat rating" for a specific IP. The issue is that due to the design of the API, the format is something like this;

{
 response: {
            xxx.xxx.xxx.xxx: <value>,
            calls_left: 299
            },
 result: "success",
 msg: null
}

xxx.xxx.xxx.xxx represents the field name i needed to retrieve data from. Immediately, you can probably see the issue i was facing; a dot character in a parse string is assumed to be a sublevel in the current path.

<value> represents the actual rating of the IP. However, the format, and data type returned from it, varies. On IP's that aren't a threat, or don't have a threat rating, it returns false as a boolean. On Search Engine crawlers, it returns "SE:<var>" (where <var> is a numerical value) as a string. On known threats, it returns "BAD:<var>" (where <var> is a numerical value). As such, i couldn't rely on a known data type being returned.

The main issue however, is that attempting to read the value from this field would obviously fail due to the dots within the field name.

like image 823
Scott P Avatar asked Feb 20 '23 19:02

Scott P


1 Answers

No need for hacks. All you need is to go through AsObject. The name, including embedded dots, is then used without treating it as a path specifier.

const Line1 = '{'
      + #13#10' response: {'
      + #13#10'            xxx.xxx.xxx.xxx: "somestring",'
      + #13#10'            calls_left: "299"'
      + #13#10'            },'
      + #13#10' result: "success",'
      + #13#10' msg: null'
      + #13#10'}';

var
  super: ISuperObject;
  res: ISuperObject;
begin
  super := SO(Line1);
  res := super.O['response'];

  writeln('S[calls_left''] on res: ', res.S['calls_left']);
  writeln('S[''xxx.xxx.xxx.xxx''] on res: ', res.S['xxx.xxx.xxx.xxx']);

  writeln('Names: ', res.AsObject.GetNames.AsString);
  writeln('Values: ', res.AsObject.GetValues.AsString);

  writeln('S[''xxx.xxx.xxx.xxx''] on res: through AsObject: ',
    res.AsObject.S['xxx.xxx.xxx.xxx']);

Gives the following results:

S[calls_left'] on res: 299
S['xxx.xxx.xxx.xxx'] on res:
Names: ["calls_left","xxx.xxx.xxx.xxx"]
Values: ["299","somestring"]
S['xxx.xxx.xxx.xxx'] on res: through AsObject: somestring
like image 159
Marjan Venema Avatar answered Mar 03 '23 21:03

Marjan Venema