I get an array of objects returned from a AJAX request in the form:
[Object { M_ID_mt="9"}, Object { M_ID_mt="12"}, 5 more...]
But because the identifier (M_ID_mt in this example) will change depending on the data returned, I want to parse this array in a loop without using the identifier.
Is there a way to pull the "data" (9, 12, ...) from each object w/o dereferencing using the identifier?
If you really receive JSON, such as
[{"M_ID_mt":"9"},{"M_ID_mt":"12"}]
there is libraries to parse/query json, may be one would do the job:
http://jsonselect.org
http://www.jsoniq.org/
https://github.com/mmckegg/json-query
...
Related
I'm consuming a Kafka topic published by another team (so I have very limited influence over the message format). The message has a field that holds an ARRAY of STRUCTS (an array of objects), but if the array has only one value then it just holds that STRUCT (no array, just an object). I'm trying to transform the message using Confluent KSQL. Unfortunately, I cannot figure out how to do this.
For example:
{ "field": {...} } <-- STRUCT (single element)
{ "field": [ {...}, {...} ] } <-- ARRAY (multiple elements)
{ "field": [ {...}, {...}, {...} ] <-- ARRAY (multiple elements)
If I configure the field in my message schema as a STRUCT then all messages with multiple values error. If I configure the field in my message schema as an ARRAY then all messages with a single value error. I could create two streams and merge them, but then my error log will be polluted with irrelevant errors.
I've tried capturing this field as a STRING/VARCHAR which is fine and I can split the messages into two streams. If I do this, then I can parse the single value messages and extract the data I need, but I cannot figure out how to parse the multivalue messages. None of the KSQL JSON functions seem to allow parsing of JSON Arrays out of JSON Strings. I can use EXTRACTJSONFIELD() to extract a particular element of the array, but not all of the elements.
Am I missing something? Is there any way to handle this reasonably?
In my experience, this is one use-case where KSQL just doesn't work. You would need to use Kafka Streams or a plain consumer to deserialize the event as a generic JSON type, then check object.get("field").isArray() or isObject(), and handle accordingly.
Even if you used a UDF in KSQL, the STREAM definition would be required to know ahead of time if you have field ARRAY<?> or field STRUCT<...>
I finally solved this in a roundabout way...
First, I created an initial stream reading the transaction as a stream of bytes using KAFKA format instead of JSON format. This allows me to put a filter conditional filter on the data so I can fork the stream into a version for the single (STRUCT) variation and a version for the multiple (ARRAY) variation.
The initial stream looks like:
CREATE OR REPLACE STREAM `my-topic-stream` (
id STRING KEY,
data BYTES
)
WITH (
KAFKA_TOPIC='my-topic',
VALUE_FORMAT='KAFKA'
);
Forking that stream looks like this with a second for a multiple version filtering for IS NOT NULL:
CREATE OR REPLACE STREAM `my-single-stream`
WITH (
kafka_topic='my-single-topic'
) AS
SELECT *
FROM `my-topic-stream`
WHERE JSON_ARRAY_LENGTH(EXTRACTJSONFIELD(FROM_BYTES(data, 'utf8'), '$.field')) IS NULL;
At this point I can create a schema for both variations, explode field, and merge the two streams back together. I don't know if this can be refined to be more efficient, but this successfully processes the transactions as I wanted.
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.
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.
JSON could mean JSON type or json string.
It starts confuse me when different library use json in two different meanings.
I wonder how other people name those variables differently.
For all practical purposes, "JSON" has exactly one meaning, which is a string representing a JavaScript object following certain specific syntax.
JSON is parsed into a JavaScript object using JSON.parse, and an JavaScript object is converted into a JSON string using JSON.stringify.
The problem is that all too many people have gotten into the bad habit of referring to plain old JavaScript objects as JSON. That is either confused or sloppy or both. {a: 1} is a JS object. '{"a": 1}' is a JSON string.
In the same vein, many people use variable names like json to refer to JavaScript objects derived from JSON. For example:
$.getJSON('foo.php') . then(function(json) { ...
In the above case, the variable name json is ill-advised. The actual payload returned from the server is a JSON string, but internally $.getJSON has already transformed that into a plain old JavaScript object, which is what is being passed to the then handler. Therefore, it would be preferable to use the variable name data, for example.
If a library uses the term "json" to refer to things which are not JSON, but actually are JavaScript objects, it is a mark of poor design, and I'd suggest looking around for a different library.
How should I handle json returned as array in Backbone.Collection's overridden parse?
I used the following for json returned as object:
parse: function(response) {
return response.results;
}
What about when json gets returned as array?
Backbone, by default, expects an array. If the array is nested within an object, you need to over-ride parse() as you have done above. However, if the response returns an array, you don't need to do anything (since that is what backbone is expecting). Finally, if you are expecting a mix of the two (that is, might be an array sometimes and might be an object the other times, see dbaseman's answer).