JSON Deserialization

So… I call a service by building some JSON with a POST. The result comes back to me as JSON. For example…lets say I get NAME, ADDRESS, CITY, STATE, ZIP, and PHONE Key:Value pairs…and perhaps PHONE is itself another set of KEY:VALUE pairs for HOMEPHONE, WORKPHONE, CELLPHONE. When this is deserialized into a Xojo.Core.Dictionary — there is no guarantee that the elements are ordered in any particular way.

You might get ADDRESS, ZIP, NAME, STATE,PHONE,CITY and the PHONE items may be CELLPHONE, HOMEPHONE, WORKPHONE.
As long as you ask for things by their DICTIONARY KEYs, you get the appropriate VALUE back. No problem.

However; if you want to “ToString” the entire thing so you can present it to the user in a more readable format, You can ITERATE over the DICTIONARY dumping KEY:VALUE pairs as TEXT… but the output will be in the bizzaro order or the Deserialization. So… It seems I have to write a “To String” class of my own that names each and every field in the order I want the output. This is fine IF I wanted to customize the order. I just want the fields output in the order they were in the original JSON result. I might be getting a hundred fields, some of which may contain dozens of sub-fields. If somebody adds a new field…the Core.Dictionary will accommodate this (no rigid model) — but I’d have to update my ToString process. I just want to “Deserialize” my JSON to Human readable Key:Value pairs in the order they are received. Perhaps Deserialization is not the way to go, should I just Parse the “Raw” JSON directly into a string?

The problem being that [quote=289011:@Robert Bednar]I just want the fields output in the order they were in the original JSON result.[/quote]

conflicts with [quote]An object is an unordered set of name/value pairs. (http://www.json.org/)[/quote]

For what it’s worth, it looks like there are some Java libraries that claim to able to preserve the order, but as one commenter said, “If someone is sending you JSON with an expected order of objects, they shouldn’t call it JSON because it’s not JSON.”

Your best bet is probably to try and clean up the raw text returned.

[quote=289031:@Scott Griffitts]The problem being that

conflicts with

For what it’s worth, it looks like there are some Java libraries that claim to able to preserve the order, but as one commenter said, “If someone is sending you JSON with an expected order of objects, they shouldn’t call it JSON because it’s not JSON.”

Your best bet is probably to try and clean up the raw text returned.[/quote]
Scott is correct as I too had been down this road previously. JSON doesn’t have guaranteed order so you would have to create a function to correctly order your dictionary/array/class etc. after you deserialize your JSON object class.

Yea, I get that… all squares are rectangles, but not all rectangles are squares. JSON does not imply any order. But something ordered would still be valid JSON. If you are receiving a JSON result from some service…it would be unwise to depend upon any implied order. However… my company created the service…and we simply use JSON as a convenient data interchange structure. It would be nice (for me anyway) if there were some sequence property that would tell me what order things were added to a dictionary. Some other “sharp” languages have a toString method that does exactly what I want in one line of code. I was going to write my own toString method using an iterator…but of course I can’t use the alphabetical order created by deserialization into a Dictionary. I didn’t investigate the older deprecated JSONItem.

If your company created the service, why not add a sequence value that is a csv string of numbers & use that to read the values in the correct order?

I would consider that Wayne, however… I am not the only client of this service. Certainly it could be done.
Meanwhile, I just Deserialized everything… and had to output the fields by KEY…which actually revealed another interesting problem for me. Some of the fields are “optional”. In my example…let’s say I want to output HOMEPHONE, WORKPHONE, and CELLPHONE. – Somebody who doesn’t have one of these does not come back as CELLPHONE : NONE – the field just doesn’t come back at all.

To combat this, I had to put IF model.HasKey(… In front of each and every field. Ugh.

Also, it’s likely the service will continue to evolve (outside of my control) – NEW fields could be added like SHOESIZE and FAVORITE_COLOR. Because I have to NAME each and every KEY I want output and in what order… I will constantly have to update my Xojo program, recompile, re-deploy.

I was kinda hoping for a “one-and-done” solution. What can I say. I’m lazy. (I have way too much to do besides keeping my programs updated to support the latest whim of the service provider)

I just want the data in the order it appears. Whatever that order is today. “Sounds” simple enough.

For that reason, it may have been easier to process/cleanup the original raw JSON text (However; some of the fields like “COMMENT” have embedded linefeeds and possibly other characters complicate a roll-your-own parser).

Did I mention that .NET has a simple one-line ToString method that returns the exact Text I want the way I want it? I’m not really dissing Xojo. It’s really good at lots-o-stuff. I’ll look at available 3rd party routines Maybe Christian has filled the gap.

Hi Robert,

Instead of recompiling your program you could store the possible field list and their order in a (text, db) file next to the main app, so that you only have to update the text file, instead of having to update the entire app.

Julen

Excellent suggestion. That had also occurred to me (I use config files to keep down hard coded values when possible) Because this JSON contains multiple “tiers” – I’ll need to identify in the config file which “tier” I want…and somehow set the tiers. For Instance: I may have the Key = Customer with NAME and AGE, but also PHONE key whose value is a dictionary that contains HOME, WORK, CELL. So those keys are not at the “Customer Tier”
I want Customer.NAME Customer.AGE Customer.PHONE.HOME , Customer.PHONE.WORK etc.

I was kinda hoping at one point that if I had a DICTIONARY “d” and I can get a value with d.Value(KEY)
If that “value” is itself a Dictionary… can I get —> d.Value(KEY).Value(OTHERKEY)
Best I could figure is I need to set “d2” = d.Value(KEY) so I can fetch d2.Value(OTHERKEY)

I might be able to use a recursive method to drill down, but it adds additional complexity…and for the moment I know my Tiers never exceed a depth of 3.

While it’s true that objects are groups of unordered name/value pairs, you can use arrays in JSON that will preserve the original data order.

This doesn’t always fit the way you want to retrieve data but if you want elements in order then you are less likely to want to also retrieve them by key-value means.

We were sending data to web browsers using object lists and it worked until a few years ago when several browsers suddenly changed their behavior and our lists arrived jumbled. A bit of refactoring into arrays fixed it.