{"filters":
[
[
"Color",
[
[
"Blue",
629,
"t12-15=blue"
],
[
"Green",
279,
"t12-15=green"
]
]
],
[
"Style",
[
[
"Contemporary / Modern",
331,
"t6-11=contemporary+modern"
],
[
"Transitional",
260,
"t6-11=transitional"
],
]
]
]}
This looks like a 4 dimensional array to me, but when I tried to use ServiceStack.Text.JsonSerializer to deserialize it, I do not get the expected result.
Looks like the values "Color" and "Style" are not in an array per se. What kind of Json structure is this?
It is indeed an array of arrays of arrays of arrays wrapped in an object. It's quite horrible, but I don't see why JsonSerializer would choke on it.
What kind of structure? Irregular, really. An object containing a field which contains an array which contains arrays in which the first item is a string, and the second item is an array containing two items which are arrays of string, number and string items .... phew!
Nothing wrong with this at all!
To me it just looks like an object containing an array of arrays that goes 4 levels deep, so its an object with one field that is a 4D array. if you want to get the 4D array you'll need to get the filters field from the json object returned
It looks approximately like that Jackson might produce when you ask it to use arrays instead of objects to represent maps.
Style and Color are just the first index of the arrays that they're in. This is almost certainly NOT what was intended. If anything Style should probably be the label (object) for the next Array rather than its sibling, no? The obvious follow-up question is who/what is producing this JSON, and who/what is consuming it... as bmarguiles asks... what *is your expectation here, given that the JSON is syntactically valid, if it's not doing what you expect... what do you expect?
Edit based on your comment:
well... since you seem to be able to rely on the fact that these are all nested arrays and that the label that you're looking for is going to be the 0th index of whatever array, you can just recurse into the array looking for that label and then treating the array that is at the 1st index with the assumption that it will contain the data you expect. It's ugly, but it looks like it will work (so long as the service that generates this doesn't change). C# has a JSON deserializer james.newtonking.com/pages/json-net.aspx . You should just use that.
Related
I have been teaching myself how to parse JSON using SwiftyJSON and the fab PokeApi.co I thought I was getting the hang of it, until I tried to get an array back of a Pokemon's different types. The JSON returned looks like this:
...
],
"base_experience": 155,
"types": [
{
"slot": 2,
"type": {
"url": "https://pokeapi.co/api/v2/type/3/",
"name": "flying"
}
},
{
"slot": 1,
"type": {
"url": "https://pokeapi.co/api/v2/type/1/",
"name": "normal"
}
}
]
}
I need to grab an array of the value for "name" within "types" and then "type". I tried lots of different suggestions from here, the SwiftyJSON guide on their Github and various other sources, and the only thing I could get to work is this:
let typesArray = json["types"].arrayValue.map({$0["type"]["name"].stringValue})
for item in typesArray {
self.currentPokemon.pokemonTypes.append(item.firstUppercased)
print("Added \(item)")
}
I am happy that I have got it to work, but I am desperately trying to get my head around parsing JSON and this just doesn't make sense to me! Could anybody please explain to me what is going on? Is there a clearer/ more readable way of doing this?
Thank you for your time!
JSON
First things first... I think you need to make sure you really understand JSON before you can wrap your head around what you are doing here. JSON objects are essentially a Key / Value object. The Key is a string and the value can be many things: array of more JSON objects, or even as simple as a string.
Best Practices
So one thing I like to do when I have to parse through JSON for any response is create an enum of strings that will have all of the "Keys" in the json. Note that if you do not assign a calue to any case and the type is String when you do pokemonApiParams.name.rawValue it will automatically return the stringified version of your case!
enum pokemonApiParams: String {
case baseExperience
case types
case slot
case type
case url
case name
}
Now when you are working with your JSON you can use this enum to help make things clearer. This is especially nice if your API response ever changed a key. You could just change the enum value and everything would work! Another reason why this is a "best practice" is it takes out these "magic strings" from your code and keeps everything in one logistical place that you can refer to later!
// This would give you 155 in your example
json[pokemonApiParams.baseExperience.rawValue]
Working through your example
Now to the part you were having trouble understanding.
First let's reconstruct your "types array" piece by piece...
let typesArray = json[pokemonApiParams.types.rawValue]
This guy creates a json object that contains the array of "types" in your response. Basic SwiftyJSON objects are great but you can be a little more specific here to get some more usage, hence why your example uses .arrayValue.
let typesArray = json[pokemonApiParams.types.rawValue].arrayValue
Now we have a JSON array object and we could go through it using various different looping functions. However you use the .map function next. This guy is super useful once you get used to it and use it some more!
Understanding .map
Basically we can map each element in our array to be something else, in this case we are using a short hand to go through the array and get only the "name" attribute of each type. So we are mapping from a [JSON] -> String.
The $0 is the shorthand I was talking about. Imagine this as your index in a for loop. The map function will walk through the entirety of the array and $0 is the object in the array that is being looked at.
Check out the map documentation too!
Putting it all together
Looking at your response each types object has a slot and a type.
So back to your example (but using our enum!):
let typesArray = json[pokemonApiParams.types.rawValue].arrayValue
.map {
$0[pokemonApiParams.type][pokemonApiParams.name.rawValue].stringValue
}
Now your typesArray is an array of strings. Another way to write this (which would be a little clearer and maybe easier to understand) is:
let typesArray = json[pokemonApiParams.types.rawValue].arrayValue
.map { (types: JSON) -> String in
types[pokemonApiParams.type.rawValue][pokemonApiParams.name.rawValue].stringValue
}
This is clearer because we have to specify our object (types) instead of using the $0 shorthand and we specify what we are returning (String).
Hopefully this is all correct and clear!
Happy coding and go catch 'em all!
I am working on a (.NET) REST API which is returning some JSON data. The consumer of the API is an embedded client. We have been trying to establish the structure of the JSON we will be working with. The format the embedded client wants to use is something I have not seen before in working with JSON. I suggested that it is no "typical" JSON. I was met with the question "Where is 'typical' JSON format documented"?
As an example of JSON I "typically" see:
{
"item" : {
"users": [ ... list of user objects ... ],
"times": [ ... list of time objects ...],
}
}
An example of the non-typical JSON:
{
"item" : [
{
"users": [ ... list of user objects ... ]
},
{
"times": [ ... list of time objects ...]
},
]
}
In the second example, item contains an array of objects, which each contain a property whose value is an array of entities. This is valid JSON. However, I have not encountered another instance of JSON that is structured this way when it is not an arbitrary array of objects but is in fact a set list of properties on the "item" object.
In searching json.org, stackoverflow.com and other places on the interwebs I have not found any guidelines on why the structure of JSON follows the "typical" example above rather than the second example.
Can you provide links to documentation that would provide recommendations for one format or the other above?
Not a link, but just straightforward answer: Items are either indexed (0, 1, 2, ...) or keyed (users, times). No matter what software you use, you can get at indexed or keyed data equally easily and quickly. But not with what you call "non-typical" JSON: To get at the users, I have to iterate through the array and find one dictionary that has a key "users". But there might be two or more dictionaries with that key. So what am I supposed to do then? If you use JSON schema, the "non-typical" JSON is impossible to check. In iOS, in the typical case I write
NSArray* users = itemDict [#"users"];
For the non-typical JSON I have to write
NSArray* users = nil;
for (NSDictionary* dict in itemArray)
if (dict [#"users"] != nil)
users = dict [#"users"];
but that still has no error checking for multiple dicts with the key "users". Which is an error that in the first case isn't even possible. So just tell them what the are asking for is rubbish and creates nothing but unnecessary work. For other software, you probably have the same problems.
Am very new to JSON interaction, I have few doubts regarding it. Below are the basic one
1) How could we call/invoke/open JSON file through Unix, I mean let suppose I have a metedata file in JSON, then how should I fetch/update the value backforth from JSON file.
2) Need the example, on how to interact it.
3) How Unix Shell is compatible to JSON, whether is there any other tech/language/tool which is better than shell script.
Thanks,
Nikhil
JSON is just text following a specific format.
Use a text editor and follow the rules. Some editors with "JSON modes" will help with [invalid] syntax highlighting, indenting, brace matching..
A "Unix Shell" has nothing directly to do with JSON - how does a shell relate to text or XML files?
There are some utilities for dealing with JSON which might be of use such as jq - but it really depends on what needs to be done with the JSON (which is ultimately just text).
Json is a format to store strings, bools, numbers, lists, and dicts and combinations thereof (dicts of numbers pointing to lists containing strings etc.). Probably the data you want to store has some kind of structure which fits into these types. Consider that and think of a valid representation using the types given above.
For example, if your text configuration looks something like this:
Section
Name=Marsoon
Size=34
Contents
foo
bar
bloh
EndContents
EndSection
Section
Name=Billition
Size=103
Contents
one
two
three
EndContents
EndSection
… then this looks like a list of dicts which contain some strings and numbers and one list of strings. A valid representation of that in Json would be:
[
{
"Name": "Marsoon",
"Size": 34,
"Contents": [
"foo", "bar", "bloh"
]
},
{
"Name": "Billition",
"Size": 103,
"Contents": [
"one", "two", "three"
]
},
]
But in case you know that each such dictionary has a different Name and always the same fields, you don't have to store the field names and can use the Name as a key of a dictionary; so you can also represent it as a dict of strings pointing to lists containing numbers and lists of strings:
{
"Marsoon": [
34, [ "foo", "bar", "bloh" ]
],
"Billition": [
103, [ "one", "two", "three" ]
]
}
Both are valid representations of your original text configuration. How you'd choose depends mainly on the question whether you want to stay open for later changes of the data structure (the first solution is better then) or if you want to avoid bureaucratic overhead.
Such a Json can be stored as a simple text file. Use any text editor you like for this. Notice that all whitespace is optional. The last example could also be written in one line:
{"Marsoon":[34,["foo","bar","bloh"]],"Billition":[103,["one","two","three"]]}
So sometimes a computer-generated Json might be hard to read and would need an editor at least capable of handling very long lines.
Handling such a Json file in a shell script will not be easy just because the shell has no notion of the idea of such complex types. The most complicated it can handle properly is a dict of strings pointing to strings (bash arrays). So I propose to have a look for a more suitable language, e. g. Python. In Python you can handle all these structures quite efficiently and with very readable code:
import json
with open('myfile.json') as jsonFile:
data = json.load(jsonFile)
print data[0]['Contents'][2] # will print "bloh" in the first example
# or:
print data['Marsoon'][1][2] # will print "bloh" in the second example
How can I convert a Postgresql stored json of this form
{"Kategorie": [{"ID": "environment", "ID": "economy"}]}
to get ["environment", "economy"] only using Postgresqls json flavoured syntax. The array in the stored source has here two elements, but may contain more (or only one). And the resulting array should result in all value elements.
This may give you something to work with:
SELECT ARRAY(select json_extract_path_text(x, 'ID') from
json_array_elements(
'{"Kategorie": [{"ID": "environment"}, {"ID": "economy"}]}'::json->'Kategorie')
as x)
The result is a text array:
{environment,economy}
It is entirely possible that there's a cleaner way to do this :)
The JSON operators documentation has the details. (This is 9.3+ only, 9.2 had very few utility functions.)
I have the following strings:
[{"result": True}]
[{"result": False}, {"info": "Describing error}]
Does this strings are correct JSON strings? Or I should use smth. like this:
{"result": False, "info": "error"}
The first one is a valid JSON string (an array with one element). The second is missing a quote, but after fixing that it is valid.
First one would resolve to an Array with one Dictionary
Second one would resolve to an Array with two Dictionaries (BTW you are missing the end quote on your string)
Third one would resolve to a Dictionary.
It will all depend on how you will want/need to consume the JSON response. All three of these can be consumed, just depends on your situation.