How to iterate JSON object keys in ActionScript 3 - actionscript-3

I'm trying to parse json in as3 that has multiple arrays like this:
{
"a1": [{
"a": 1,
"b": "2",
"c": 3
},
{
"a": 1,
"b": "2",
"c": 3
}
],
"a2": [{
"a": 1,
"b": "2",
"c": 3
},
{
"a": 1,
"b": "2",
"c": 3
}
],
"a3": [{
"a": 1,
"b": "2",
"c": 3
},
{
"a": 1,
"b": "2",
"c": 3
}
]
}
I don't really know hot to iterate through it to get the values out of each array though. I assume I'd use a for loop and append it to the end of the array name "a", but I'm not sure how to write this (if that's even the right way to approach it).

What you have is not simply arrays, but a mixture of objects (also known as hashes or associative arrays), as well as lists (arrays).
To iterate both the objects and lists you can use a for each loop:
(assuming your object is called data)
// loop parent object
for each (var parent:Object in data)
{
trace(parent);
// loop child array
for each (var child:Object in parent)
{
trace(child);
// loop grandchild object
for each (var grandchild:Object in child)
{
trace(grandchild);
}
}
}
Please bear in mind that this code is untested and you may need to cast the Object types to more specific types such as (Array)Object in order to properly iterate them.

you could iterate through the JSON like this:
for (var parent:Object in json)
{
for (var child:Object in json[parent] )
{
trace(json[parent][child].a);
trace(json[parent][child].b);
trace(json[parent][child].c);
}
}
you can use "parent" and "child" as keys to parse out the values

Why reinvent the wheel. There are a ton of JSON libraries out there.
This article may help: Mike Chambers - Using JSON with Flex 2 and ActionScript 3

Related

jq: how to replace keys with values ​from other keys whose ​are in strings of some array

Consider following array:
{
"A": 100,
"B": 200,
"C": "ccc",
"arr": [
{
"result": ".R1.R3",
"fmt": "%s::%s::baz",
"vals": [".A", ".B"]
},
{
"result": ".R2.R4",
"fmt": "%s/%s",
"vals": [".A", ".C"]
}
]
}
I need to replace keys according some format with values ​​from other keys whose ​​are in strings of some array.
Desired output:
{
"A": 100,
"B": 200,
"C": "ccc",
"R1": {"R3": "100::200::baz"},
"R2": {"R4": "100/ccc"}
}
You didn't specify what language you use in the .vals array items to reference into the document. If you were trying to execute (arbitrary) jq code from there, know that jq cannot do that with code provided as a string value. jq also doesn't provide printf-style substitutions using %s (and others). Therefore, you either need to re-implement a whole bunch of (third-party) functionality, or revert to a simpler scheme describing your references and substitutions.
For the sake of simplicity, this solution just removes the first character (the dot) from the .vals array items and treats the result as top-level field name, and then simply replaces each occurrence of a literal %s with the next value. This should give you an overview of the general technique.
. as $top | reduce .arr[] as $a (del(.arr); .[$a.result] = (
reduce $a.vals[][1:] as $val ($a.fmt; sub("%s"; $top[$val] | #text))
))
{
"A": 100,
"B": 200,
"C": "ccc",
".R1": "100::200::baz",
".R2": "100/ccc"
}
Demo
One quite simple way of improving the reference language is to instead use path expressions jq provides functions for. They are represented as arrays with field names as strings items and array indices as number items. .A would become ["A"], .A[3].B would become ["A",3,"B"], and so on. Thus, assume your input looked like this:
{
"A": 100,
"B": 200,
"C": "ccc",
"arr": [
{
"result": ".R1",
"fmt": "%s::%s::baz",
"vals": [["A"], ["B"]]
},
{
"result": ".R2",
"fmt": "%s/%s",
"vals": [["A"], ["C"]]
}
]
}
Then you could use getpath to evaluate the given path expressions as above:
. as $top | reduce .arr[] as $a (del(.arr); .[$a.result] = (
reduce $a.vals[] as $path ($a.fmt; sub("%s"; $top | getpath($path) | #text))
))
{
"A": 100,
"B": 200,
"C": "ccc",
".R1": "100::200::baz",
".R2": "100/ccc"
}
Demo
Edit: As the question has been modified with the .result value now also being subject to reference interpretation, measures taken for .vals therefore apply to it as well. This implies changing the suggested source document format to use path expressions as in "result": ["R1", "R3"], and changing the assignment in the suggested code from .[$a.result] = ... to setpath($a.result; ...):
{
"A": 100,
"B": 200,
"C": "ccc",
"arr": [
{
"result": ["R1", "R3"],
"fmt": "%s::%s::baz",
"vals": [["A"], ["B"]]
},
{
"result": ["R2", "R4"],
"fmt": "%s/%s",
"vals": [["A"], ["C"]]
}
]
}
. as $top | reduce .arr[] as $a (del(.arr); setpath($a.result;
reduce $a.vals[] as $path ($a.fmt; sub("%s"; $top | getpath($path) | #text))
))
{
"A": 100,
"B": 200,
"C": "ccc",
"R1": {
"R3": "100::200::baz"
},
"R2": {
"R4": "100/ccc"
}
}
Demo

Is it possible to add a key-value pair to a map of unknown type in Go?

I have multiple JSON files with different formats. All of them consist of an array which contain maps. The maps, however, have different structures.
a.json
[
{
"a": "b",
"c": ["d", "e"]
}
]
b.json
[
{
"f": ["g", "h"],
"i": {"j": "k"}
}
]
Thr structure of the internal maps is irrelevant. I just want to add a new key-value pair to all of them, so they look like this
a.json
[
{
"new_key": "new_value",
"a": "b",
"c": ["d", "e"]
}
]
b.json
[
{
"new_key": "new_value",
"f": ["g", "h"],
"i": {"j": "k"}
}
]
You can use a slice of maps:
var data []map[string]interface{}
You can unmarshal:
json.Unmarshal(jsonData,&data)
and then add the keys:
for i:=range data {
data[i]["new_key"]="newValue"
}
Of course, you have to do the necessary error checks, and make sure data[i] is not nil.

Conditional deletion from array of field A with condition on field B

Let's say I have a json with an array inside. Say that the elements of this array are objects with keys A and B. I would like to remove the B objects on the elements where A objects meet a certain condition.
For example, I would like to remove the B objects where A is greater than 5, transforming
{
"title": "myTitle",
"myArray": [
{
"A": 1,
"B": "foo"
},
{
"A": 4,
"B": "bar"
},
{
"A": 7,
"B": "barfoo"
},
{
"A": 9,
"B": "foobar"
}
]
}
into
{
"title": "myTitle",
"myArray": [
{
"A": 1,
"B": "foo"
},
{
"A": 4,
"B": "bar"
},
{
"A": 7
},
{
"A": 9
}
]
}
The task seems easy enough and if I had't have to keep the A's it would be a simple del(select..) thing. There surely must be an elegant way to do this as well?
Thank you!
You can still use a del(select..) thing.
.myArray[] |= del(select(.A > 5) .B)
demo at jqplay.org

Combine two objects using JsonPath

Suppose I have json like this:
[
{
"a": 1,
"b": 2,
"c": 3,
},
{
"a": 1,
"b": 2,
"d": 4
}
]
Is it possible to write a JsonPath which will give me:
{
"a": 1,
"b": 2,
"c": 3,
"d": 4
}
The order of the elements in the list is not sure, however the element names I know beforehand. So I thought I could use JsonPath to select all elements with names 'a', 'b', 'c' or 'd' and put them in a single object. However, I now have tried several things and I start to doubt whether what I want is possible.
For example I can select an object which has an element c with:
$[?(#.c)]
And I can also select just the value of d with something like:
$..d
But I can not find any way to comebine them into a single object. Is what I want possible with JsonPath or is this a limitation of JsonPath?
I think the appropriate way to do this is to remove the second object and apply the difference between them to the first one:
[
{ "op": "remove", "path": "/1" },
{ "op": "add", "path": "/0/d", "value": 4 }
]
Assuming you're OK with polyfilling for IE (it's ES6), use Object.assign:
const object1 = {
a: 1,
b: 2,
c: 3
};
const object2 = {
d: 4
}
const objectMerged = Object.assign({}, object1, object2);
console.log(objectMerged.c);
console.log(objectMerged.d);
For full details, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Browser_compatibility

Whats the standard of defining an empty object in JSON

I have an issue with my application. It is returning a JSON file of an array of objects. The application is defining an empty object inside the array of objects as text value string whose value is defined as an object in the other element of array. Please see the value of the key "b" in the example.
For Eg:
{
"result": [{
"a": "1",
"b": {
"c1": "31",
"c2": "32"
}
}, {
"a": "5",
"b": ""
}
]
}
I want to know if that is a correct way of defining the key "b" as an empty object.
Thanks in advance!!
An empty object is defined by {}:
"b": {}
I.e. use the usual object delimiters but don't add any key-values.
What you defined is an empty string.
In JSON, an object is defined with { }, which is exactly what you would represent an empty object as.
{
"result": [
{
"a": "1",
"b": {
"c1": "31",
"c2": "32"
}
}, {
"a": "5",
"b": { }
}
]
}