Issue with ordering JSON keys when marshalling an ordered map in Golang - json

I have a requirement to iterate a given piece of JSON, and where an array contains a single item to convert that into a map. This is quite easy to do.
The catch is, I need to product a piece of JSON back to the client that is in the same order it was presented.
I have found some guides about using an OrderedMap, but that's inconsistent for me.
Sometimes I get the correct order, sometimes not.
https://go.dev/play/p/b9hmS9BEymy
Can anyone advise? From the logging it appear the issue may be with unmarshalling the incoming JSON
I am really reluctant to use structs, as the real JSON I need to process is very complex, and will need a huuuge amount of work as there are many variations.

Unmarshalling json will not respect order, as you use map[string]interface{}. Map in golang is a hashmap, so no surprise there. What you should do is create an UnmarshalJSON function as well and do custom unmarshalling, otherwise there is no way to preserve order.
You can use standard unmarshalling for every other type, except map, which should make it a lot easier. If you want details on how to do that, I can explain that too

If anyone ever stumbles across this, I was able to solve it by using this package
https://gitlab.com/c0b/go-ordered-json
I had to Unmarshall the JSON into an orderedmap so the map contained the keys in the order they were presented, and then I was able to work through them from there:
var om *OrderedMap = NewOrderedMap()
err := json.Unmarshal([]byte(input), om)

Related

Swift unable to preserve order in String made from JSON for hash verification

We receive a JSON object from network along with a hash value of the object. In order to verify the hash we need to turn that JSON into a string and then make a hash out of it while preserving the order of the elements in the way they are in the JSON.
Say we have:
[
{"site1":
{"url":"https://this.is.site.com/",
"logoutURL":"",
"loadStart":[],
"loadStop":[{"someMore":"smthelse"}],
"there's_more": ... }
},
{"site2":
....
}
]
The Android app is able to get same hash value, and while debugging it we fed same simple string into both algorithms and were able to get out same hash out of it.
The difference that is there happens because of the fact that dictionaries are unordered structure.
While debugging we see that just before feeding a string into a hash algorithm, the string looks like the original JSON, just without the indentations, which means it preserves the order of items in it (on Android that is):
[{"site1":{"url":"https://this.is.site.com/", ...
While doing this with many approaches by now I'm not able to achieve the same: string that I get is different in order and therefore results in a different hash. Is there a way to achieve this?
UPDATE
It appears the problem is slightly different - thanks to #Rob Napier's answer below: I need a hash of only a part of incoming string (that has JSON in it), which means for getting that part I need to first parse it into JSON or struct, and after that - while getting the string value of it - the order of items is lost.
Using JSONSerialization and JSONDecoder (which uses JSONSerialization), it's not possible to reproduce the input data. But this isn't needed. What you're receiving is a string in the first place (as an NSData). Just don't get rid of it. You can parse the data into JSON without throwing away the data.
It is possible to create JSON parsers from scratch in Swift that maintain round-trip support (I have a sketch of such a thing at RNJSON). JSON isn't really that hard to parse. But what you're describing is a hash of "the thing you received." Not a hash of "the re-serialized JSON."

SwiftyJSON array elements?

I have tried finding how to work with SwiftyJSON arrays but nothing seems to work.
My function before using swift was:
json.brands.count
json.brands[0].name
json.brands[0].subname
json.brands[0].value
json.brands[1].name
json.brands[1].subname
json.brands[1].value
//Etc
Now I’m using:
json[“brands”][“name”].exists()
json[“brands”][“name”].string
But struggling to insert [0] [1] etc to make it work.
*I’m aware not to use 3rd party content if possible but my JSON api won’t work without a 3rd party. As there is 10 user inputs from a database which has thousands of dynamic entries to the JSON, so I can’t code them all, then there are objects which might be present and if they are present they might contain a value.
I tried the traditional swift json decoder approach but to catch all the errors with a dynamic nested JSON was giving me a headache.*
You can try this :
json[“brands”][0][“name”].exists()
json[“brands”][0][“name”].string
json[“brands”][1][“name”].exists()
json[“brands”][1][“name”].string
Hope it helps...

How to create diff of two generic T:Codable structs in Swift?

Given: I have two structs of the same type, conforming to Codable Protocol.
The structs can be multi-level (nested properties, surely also are conforming to Codable). The type is not known at the time of implementation, so i consider it generic, conforming to Codable.
One object is "base" (say, received from server), second (actually the copy of "base"), but modified inside application.
The intention is: To send a request for saving new data, but sending only the "diff" of two structs. So, only the fields, that are different should be present in resulting JSON.
The straightforward way with getting JSON strings for both structs and manipulating with them, is understandable, but seem to be the last-chance approach...
I've tried the approach with Mirror, and recursion, but now have managed to make it work only for first level - on the second level of nesting i've lost the type of nested property (if struct or array), and cannot cast it right then...
I wonder if it can be made somehow with custom encoder?
P.S.: the generic type should have all properties as Optionals, so should not provide any explicit initializers.
Instead of your "last-chance approach" -- matching JSON strings -- you could use JSONSerialization.jsonObject to convert the JSON data to Foundation objects and perform your comparison on that higher level of abstraction (if that's what you meant in your question in the first place, then sorry - nevermind).
Of course you'd pay an extra penalty of converting your Codable objects to data and then parsing that data into an object hierarchy.

Get field name that err's in Go json unmarshal

I have some big json files that are slightly different in the types that the fields contain.
{ "a":"1" }
vs.
{ "a":1 }
When I unmarshal the second I get:
cannot unmarshal number into Go value of type string
However since these jsons are large I would like to have the actual field that is in error so I can fix them. The UnmarshalTypeError does not hold the Struct's field type.
Does anybody know of a way to get to field name? (not debugging I have a lot of different fields that err)
[EDIT]
I know how to solve the type conversion. What I need is a method to see what fields I need to apply that conversion to.
The short answer is that you can't.
However, to fix your problem, there is multiple solutions:
Dive into the json.Unmarshal source code to change its working and add the information you need: copy the function to a local package, do your edits, and use this function
Use a thrid-party tool to help you, for example a JSON validator compatible with JSON Schema: here is an online example, there is probably some better-suited tool
Now the UnmarshalTypeError, contains the field name.

Using Freepascal\Lazarus JSON Libraries

I'm hoping for a bit of a "simpletons" demo\explanation for using Lazarus\Freepascal JSON parsing. I've asked a question here but all the replies are "read this" and none of them are really helping me get a grasp because the examples are bit too in-depth and I'm seeking a very simple example to help me understand how it works.
In brief, my program reads an untyped binary file in chunks of 4096 bytes. The raw data then gets converted to ASCII and stored in a string. It then goes through the variable looking for certain patterns, which, it turned out, are JSON data structures. I've currently coded the parsing the hard way using Pos and ExtractANSIString etc. But I'vesince learnt that there are JSON libraries for Lazarus & FPC, namely fcl-json, fpjson, jsonparser, jsonscanner etc.
https://bitbucket.org/reiniero/fpctwit/src
http://fossies.org/unix/misc/fpcbuild-2.6.0.tar.gz:a/fpcbuild-2.6.0/fpcsrc/packages/fcl-json/src/
http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/fcl-json/examples/
However, I still can't quite work out HOW I read my string variable and parse it for JSON data and then access those JSON structures.
Can anyone give me a very simple example, to help getting me going?
My code so far (without JSON) is something like this:
try
SourceFile.Position := 0;
while TotalBytesRead < SourceFile.Size do
begin
BytesRead := SourceFile.Read(Buffer,sizeof(Buffer));
inc(TotalBytesRead, BytesRead);
StringContent := StripNonAsciiExceptCRLF(Buffer); // A custom function to strip out binary garbage leaving just ASCII readable text
if Pos('MySearchValue', StringContent) > 0 then
begin
// Do the parsing. This is where I need to do the JSON stuff
...
See parsedemo.pp, specially parsestring. Just modify the doparse routine to extract whatever information you need from the j:TJSonData object.
The simpledemo.pp demonstrates how to disect a jsondata object.
Then read the src/README.txt file. It seems to hint on a bunch of properties of a jsonobject that allow to get fields by name. This only works for structures json objects like array and object.
I do agree that a demo for that would be a good thing. If you make it, please submit it to mantis.
Disclaimer: I have nothing to do with the json package, I got the above from a quick glance at the (admittedly 2.7.1) source.