Help with JSON Objects / JSON Dictionaries

I must admit to being a bit frustrated trying to figure out both JSON and JSON Objects and/or Dictionaries with JSON in 'em. Would you guys mind looking at the example code below and pointing me to the right parts of the documentation please?

In the sample code below, I also tried using Str(t.Value), which throws a compile error.

That also tells me that I don’t know enough about types in Xojo. Bedtime reading! :slight_smile:

Thanks
-Paul

  dim count as integer
  dim rc as Integer
  dim inputString as String
  dim AKEY as String
  dim AVALUE as String
  
  inputString = "{""name"": ""Kha\\u0304lid Muh\\u0323ammad \\u02bbAli\\u0304 al-H\\u0323a\\u0304jj"", ""personal_name"": ""Kha\\u0304lid Muh\\u0323ammad \\u02bbAli\\u0304 al-H\\u0323a\\u0304jj"", ""last_modified"": {""type"": ""/type/datetime"", ""value"": ""2008-08-20T17:57:09.66187""}, ""key"": ""/authors/OL1000057A"", ""type"": {""key"": ""/type/author""}, ""revision"": 2}"
  
  dim JSONinput As  new JSONItem(inputString)
  MsgBox (JSONinput.ToString)
  
  'That worked, now iterate over the JSON object, display the key pairs in a textbox
  msgBox("The JSON object has " + Str(JSONinput.Count) + " elements." + EndOfLine)
  
  for count = 0 to JSONinput.Count-1
    AKEY = Str(JSONinput.Name(count))
    'AVALUE = Str(JSONinput.Value(AKEY))
    'msgBox("Key = " + AKEY + " : " + AVALUE + EndOfLine)
  next count
  
  'That didn't work too well, with data type exceptions on the AVALUE variable
  'How about as a dictionary as at (http://www.xojo.com/blog/en/2015/04/newframeworkjson.php)?
  
  
  ' First - aRecord throws an invalid cast exception if defined as "Dictionary" like shown in the example
  ' Compiles if I use the Xojo.Core qualifiers.
  Dim aRecord as Xojo.Core.Dictionary = Xojo.Data.ParseJSON(inputString.ToText)
  
  'And then I run into type exceptions. Not sure how to determine the data type and make appropriate casts/conversions
  for each t as Xojo.Core.DictionaryEntry in aRecord
    ' msgbox ("Key: " + t.Key + EndOfLine + "Value: "+ t.Value +  EndOfLine) ' causes type exceptions
    msgbox ("Key: " + t.Key + EndOfLine + "Value: " +  EndOfLine) 'works
    
  next t
  
  

You don’t use Str with a Variant, just use it as if it was a string.

Surely I am doing something very stupid here, but when I try to use t.Value as a string, it will throw an exception when it hits revision in the data, which is numeric. I must go read more about this Variant type- I think I am making assumptions based on other languages there. Thanks though - I appreciate the pointers!

  • Ah, on the second iteration of the loop, it is returning a variant type 9 (OBJECT) - I guess because it is picking up the “last modified” key which is a /type/datetime. I suppose I have to cast the object type to a string or something to be able to access it?

The only type of object it can be is another JSONItem, found under last modified and type. If the value is TypeObject, cast it to JSONItem and walk it independently.

Thanks Kem - that did the trick. I was missing that there were dictionaries/JSON Objects embedded in the input JSON. Once that sunk through my thick head, it all cleared right up.

Super appreciate the help. I owe you one. :slight_smile:

I was on my phone before so it was hard to be verbose. Let me give you more detail.

In Xojo, a Variant is a “hold anything” type that auto-converts, to the best of its ability, to however you’re using it. If it holds the string “3.14” and you try to use it as a double, it will accommodate you. If it holds the integer 30 and you try to use it as a string, it will return “30”. But if it can’t do the conversion, it will raise an exception, such as if it holds an object and you try to access it as a string.

JSON, at its top level, can be an “object” or an “array”. The object is akin to a Xojo Dictionary except the key can only be a string. The array is akin to a Xojo array of Variant.

A single JSON value can be nil, a number, a boolean, a string, or another JSON object or array. In Xojo, a JSONItem value, returned as a Variant, can only be one of those too. You can act as if they are all strings except for the objects and arrays which, as I mentioned, will be another JSONItem.

In your example, the JSON is an object (dictionary) with the keys “name”, “personal_name”, “last_modified”, “key”, “type”, and “revision”. All of those will return strings except for last_modified and type, both of which will return JSONItems. Within each are their own sets of keys and values.

I hope this helped a bit.

Thanks Again Guys - got all that working except for the last part, which I assume is pretty easy but is difficult for me to wrap my head around.

I have successfully retrieved the data from the RDF/JSON format, modified it to suit out needs, and am now ready to stack it back in a database where it can me queried most easily.

Except those darn Unicode characters mean I either need to re-notate the characters in the outgoing data, or go in and change not on the database, but innumerable programs in C, COBOL, and other languages to deal with Unicode. A big task.

So, I found a note on the internet about setting EncodeUnicode to true, but I can’t seem to find whatever class or objects supports that process. I have converted the JSON into dictionaries, but at the point it is time to insert the data back into the database, the data is all setup as string variables that are to be used in the SQL.

I know the database will bark at me if I try to send it unicode characters, so need to even try that. :slight_smile:

How do I cause a string with Unicode in it to become an ASCII string with the unicode characters notated in an expanded format?

Thanks! Last stupid question for a while, I hope. :slight_smile:

Yours
-Paul

Use my drop-in replacement, JSONItem_MTC, instead of the native JSONItem. It works exactly the same way so you just have to change references from JSONItem to JSONItem_MTC, but, aside from addressing some bugs in the native JSONItem, it has the additional property EncodeUnicode that can be set to JSONItem_MTC.EncodeType.All. That will force all Unicode characters into the “\uXXXX” notation.

The bonus is that it’s faster than the native JSONItem when parsing and rendering text.

You can get it from here:

https://github.com/ktekinay/JSONItem_MTC

Note that the new framework parsing/generating is faster still, but the new Xojo.Core.Dictionary is slower than the native Dictionary, so your entire code might be slower than using JSONItem_MTC. I found this out the hard way. :frowning: But the new framework has no options, which is another reason to stick with JSONItem_MTC for now.

Have to do a small recode to use JSONItem_MTC code instead of dictionaries, but that is faster than delving into and coding unicode transforms. Especially since you have already mastered them! :slight_smile:

It seems odd that dictionaries will ingest unicode notation in ASCII text, but have no provision to emit the same format. Not very symmetric.

Yours,
-Paul

According to the standard (the way I read it), you shouldn’t need to since the JSON encoding should be UTF8 or UTF16 anyway so the meaning of the bytes would be clear. But I thought there might be a need to force it, even if I never had that need. Glad it was helpful.

BTW, you can create an empty Dictionary-type JSONItem (or JSONItem_MTC) with:

dim j as new JSONItem_MTC( "{}" )

Note that this will act as a case-sensitive Dictionary.