SwiftyJSON- Iterate through objects with ID which are not an array - json

I am making a request to an API that sometimes returns an array of simple JSON objects, which I am parsing with a simple "for i in count" loop, where I use SwiftyJSON to append json[i]["city"]. For example:
[{"city":"Lakefront","code":"NEW","country":"United States","municipality":"New Orleans","isChild":false,"hasChild":false},
{"city":"Auckland - Auckland International Airport","code":"AKL","country":"New Zealand","municipality":"Auckland","isChild":false,"hasChild":false},
{"city":"Blenheim","code":"BHE","country":"New Zealand","municipality":"Blenheim","isChild":false,"hasChild":false}]
However, in certain cases, the API will return an object with multiple pairs of keys and object values, which I am having trouble parsing with SwiftyJSON. For example:
{"2":{"city":"New York","code":"NYC","country":"United States","municipality":"New York","isChild":false,"hasChild":true},
"32":{"city":"John F. Kennedy - NY","code":"JFK","country":"United States","municipality":"New York","isChild":true,"hasChild":false},
"414":{"city":"LaGuardia - NY","code":"LGA","country":"United States","municipality":"New York","isChild":true,"hasChild":false}}
In this second case, is there a way to loop through the first object with SwiftyJSON, and get the object value noting that I will not know the ID (2, 32, 414) in advance?
Thanks!

In your first case you have an array of dictionaries. In the second case you have a dictionary of dictionaries. I haven't used SwiftyJSON in long enough that I don't remember how it works, but that should be enough to get you going.

Related

Create json array of records with Delphi

I'm trying to create a json with multiple records by following this example: Generate a sample JSON with an array in it in Delphi XE5
must be the same way, except that when I add the array to the object
JSonObj.AddPair (TJSONPair.Create ('records', TJSONArray));
returns the error:
"There is the overloaded version of 'Create' that can be called with arguments These"
How do I add to the array object?
If I convert an array to string and add, to receive the amounts can not treat as an array ...
You're passing it the class reference for a JSON array. You need to pass it an instance.
arr := TJSONArray.Create;
JSONObj.AddPair(TJSONPair.Create('records', arr));
Look carefully at the answers in the question you link to, and you'll see this is exactly what they're doing, too.

Is {0:{"id":1,...},{"id:2,....}} a other reprensation of a JSON list like [{"id":1,...},{"id:2,....}]

I have a little dilema. I have a backend/Frontend Application that comunicates with a JSON based REST Api.
The backend is written in PHP(Symfony/jmsserializer) and the Frontend in Dart
The communication between these two has a little Problem.
For most List Data the backend responds with a JSON like
[{"id":1,...},{"id:2,....}]
But for some it responds with
{"0":{"id":1,...}, "1":{"id:2,....}}
Now my Question is should the backend respond with the later at all or only with the first?
Problem
You usually have a list of objects. You sometimes get an object with sub-objects as properties.
Underlying issue
JS/JSON-Lists are ordered from 0 upwards which means that if you have PHP-Array which does not respect this rule json_encode will output a JS/JSON-Object instead using the numeric indices as keys.
PHP-Arrays are ordered maps which have more features that the JSON-Lists. Whenever you're using those extra features you won't be able to translate directly into JSON-Lists without loosing some information (ordering, keys, skipped indices, etc.).
PHP-Arrays and JSON-Objects on the other hand are more ore less equivalent in terms of features and can be correctly translated between each other without any loss of information.
Occurence
This happens if you have an initial PHP-Array of values which respects the JS/JSON-List rules but the keys in the list of objects are modified somehow. For example if you have a custom indexing order {"3":{}, "0":{}, "1":{}, "2":{}} or if you have (any) keys that are strings (ie. not numeric).
This always happens if you want to use the numeric id of the object as the numeric index of the list {"123":{"id": 123, "name": "obj"}} even if the numeric ids are in ascending order... so long as they are not starting from 0 upwards it's not a json-list it's a json-object.
Specific case
So my guess is that the PHP code in the backend is doing something like fetching a list of objects but its modifying something about it like inserting them by (string) keys into the array, inserting them in a specific order, removing some of them.
Resolution
The backend can easily fix this by using array_values($listOfObjects) before using json_encode which will reindex the entire list by numeric indices of ascending value.
Arrays and dictionaries are two separate types in JSON ("array" and "object" respectively), but PHP combines this functionality in a single array type.
PHP's json_encode deals with this as follows: an array that only contains numeric keys ($array = ['cat', 'dog']) is serialized as JSON array, an associative array that contains non-numeric keys ($array = ['cat' => 'meow', 'dog' => 'woof']) is serialized as JSON object, including the array's keys in the output.
If you end up with an associative array in PHP, but want to serialize it as a plain array in JSON, just use this to convert it to a numerical array before JSON encoding it: $array = array_values($array);

Use JSON.stringify but the data still have array, what does it mean?

I have a data which are object array. It contains object arrays in a tree structure. I use JSON.stringify(myArray) but the data still contain array because I see [] inside the converted data.
In my case, I want all the data to be converted into json object not array regarding I need to used the data on TreeTable of SAPUI5.
Maybe I misunderstand. Please help me clear.
This is the example of the data that I got from JSON.stringify.
[{"value":{"Id":"00145E5BB2641EE284F811A7907717A3",
"Text":"BI-RA Reporting, analysis, and dashboards",
"Parent":"00145E5BB2641EE284F811A79076F7A3","Type":"BMF"},
"children":[{"value":{"Id":"00145E5BB2641EE284F811A7907737A3",
"Text":"WebIntelligence_4.1","Parent":"00145E5BB2641EE284F811A7907717A3",
"Type":"TWB"},"children":[{"value":{"Id":"00145E5BB2641EE284F811A7907757A3",
"Text":"Functional Areas","Parent":"00145E5BB2641EE284F811A7907737A3","Type":"TWB"},
"children":[{"value":{"Id":"00145E5BB2641EE284F811A7907777A3",
"Text":"CHARTING","Parent":"00145E5BB2641EE284F811A7907757A3","Type":"TWB"},
"children":[{"value":{"Id":"001999E0B9081EE28AB706BE26631E93",
"Text":"Drill","Parent":"00145E5BB2641EE284F811A7907777A3","Type":"TWB"},
"children":[{"value":{"Id":"001999E0B9081EE28AB706BE26633E93",
"Text":"[AUTO][ACCEPT] Drill on charts DHTML","Parent":"001999E0B9081EE28AB706BE26631E93",
"Type":"TWB","Ref":"UT_WEBI_CHARTS_DRILL_HTML"}},{"value":{"Id":"001999E0B9081EE28AB706BE26635E93",
"Text":"[AUTO][ACCEPT] Drill on charts JAVA","Parent":"001999E0B9081EE28AB706BE26631E93",
"Type":"TWB","Ref":"UT_WEBI_CHARTS_DRILL_JAVA"}}]},...
The output that I want shouldn't be array of object but should be something like...
{{"value":{
"Id":"00145E5BB2641EE284F811A7907717A3",
"Text":"BI-RA Reporting, analysis, and dashboards",
"Parent":"00145E5BB2641EE284F811A79076F7A3","Type":"BMF"},
"children":{
{"value":{
"Id":"00145E5BB2641EE284F811A7907737A3",
"Text":"WebIntelligence_4.1",
"Parent":"00145E5BB2641EE284F811A7907717A3",
"Type":"TWB"},
"children":{
{"value":{
"Id":"00145E5BB2641EE284F811A7907757A3",
"Text":"Functional Areas",
"Parent":"00145E5BB2641EE284F811A7907737A3",
"Type":"TWB"},...
JSON.stringify merely converts JavaScript data structures to a JSON-formatted string for consumption by other parsers (including JSON.parse). If you want it to stringify to a different value, you must change the source data structures first.
However, it seems that this can't be represented as anything other than an array because you have duplicate keys (i.e. value appears more than once). That would not be valid for a JavaScript object or a JSON representation of such.
I think what you want is
JSON.stringify(data[0]);
or perhaps
JSON.stringify(data[0].value);
where data is the object you passed in the question

JSON members order in ActionScript 3.0

I'm using built-in functionality to create JSON string in Flash app.
Here example of my source code
objStr = JSON.stringify(
{
version:"1.0",
skin:"white",
palette:{dataColor:"#0397d6",negativeDataColor:"#d40000",toolbarColor:"#056393"}
});
I have a problem. Every time I've started my app (not executing createJSON function), I have different member order in JSON string as result.
For example:
{"version":"1.0","palette":{"negativeDataColor":"#d40000","dataColor":"#0397d6","toolbarColor":"#056393"},"skin":"white"}
or
{"palette":{"negativeDataColor":"#d40000","toolbarColor":"#056393","dataColor":"#0397d6"},"version":"1.0","skin":"white"}
How can I fix it.
JSON objects are unordered, see JSON.org:
JSON is built on two structures:
A collection of name/value pairs. In various languages, this is
realized as an object, record, struct, dictionary, hash table, keyed
list, or associative array. An object is an unordered set of name/value pairs
An ordered list of values. In most languages, this is realized as an
array, vector, list, or sequence. An array is an ordered collection of values.
Order really doesn't matter since you should be retrieving the values by the key rather than iterating over them.

Find Dict Values from csv.DictReader

I'm trying to take a csv file and turn it into a dictionary, via csv.DictReader. After doing this, I want to modify one of the columns of the dictionary, and then write the data into a tsv file. I'm dealing with words and word frequencies in a text.
I've tried using the dict.value() function to obtain the dictionary values, but I get an error message saying "AttributeError: DictReader instance has no attribute "values""
Below is my code:
#calculate frequencies of each word in Jane Austen's "Pride and Prejudice"
import csv
#open file with words and counts for the book, and turn into dictionary
fob = open("P&P.csv", "r")
words = csv.DictReader(fob)
dict = words
#open a file to write the words and frequencies to
fob = open("AustenWords.tsv", "w")
#set total word count
wordcount = 120697
for row in words:
values = dict.values()
print values
Basically, I have the total count of each word in the text (i.e. "a","1937") and I want to find the percentage of the total word count that the word in question uses (thus, for "a", the percentage would be 1937/120697.) Right now my code doesn't have the equation for doing this, but I'm hoping, once I obtain the values of each row, to write a row to the new file with the word and the calculated percentage. If anyone has a better way (or any way!) to do this, I would greatly appreciate any input.
Thanks
To answer the basic question - "why am I getting this error" - when you call csv.DictReader(), the return type is an iterator not a Dictionary.
Each ROW in the iterator is a Dictionary which you can then use for your script:
for row in words:
values = row.values()
print values
Thank goodness for Matt Dunnam's answer (I'd reply to it but I don't see how to). csv.DictReader objects are, quite counter-intuitively, NOT dictionary objects (although I think I am beginning to see some usefulness in why not). As he says, csv.DictReader objects are an iterator (with my intro level to python, I think this is like a list maybe). Each entry in that object (which is not a dictionary) is a dictionary.
So, csv.DictReader returns something like a list of dictionaries, which is not the same as returning one dictionary object, despite the name.
What is nice, so far, is that csv.DictReader did preserve my key values in the first row, and placed them correctly in each of the many dictionary objects that are a part of the iterable object it actually returned (again, it does not return a dictionary object!).
I've wasted about an hour banging my head on this, the documentation is not clear enough, although now that I understand what type of object csv.DictReader returns, the documentation is a lot clearer. I think the documentation says something like how it returns an iterable object, but if you think it returns a dictionary and you don't know if dictionaries are iterable or not then this is easy to read as "returns a dictionary object".
The documentation should say "This does not return a dictionary object, but instead returns an iterable object containing a dictionary object for each entry" or some such thing. As a python newbie who hasn't coded in 20 years, I keep running into problems where the documentation is written by and for experts and it is too dense for beginners.
I'm glad it's there and that people have given their time to it, but it could be made easier for beginners while not reducing its worth to expert pythonistas.