How to distinguish an object from an array in JSON? - json

I'm using PostgreSQL 9.3.6 and I have a json type column. Is there any way to find out whether we are dealing with an array or an object? I mean:
SELECT '["x", "y"]'::json
SELECT '{"0": "x", "1": "y"}'::json
Or maybe it's possible to translate one notation to another? The thing is that I have to extract values which are nested inside an array or an object.
I can call "json_each" on an object, but it fails on an array:
SELECT * FROM json_each('{"0": "x", "1": "y"}'::json)
Unfortunately I can't upgrade to 9.4... which means I can't use jsonb type or new operators to test it... I appreciate your help.

Related

How to extract all elements in a JSON array using Redshift?

I want to extract from a JSON which has more JSONs nested inside, all the elements whose title is 'title2'. I have the code working on MySQL but I can not translate it into Redshift.
JSON structure:
{"master-title": [{"title": "a", "title2": "b"},{"title": "c", "title2: "d", "title3": "e"}], "master-title2": [{"title": "f", "title2": "g", "title3": "h"},{"title": "i", "title2": "j", "title3": "k"}]}
MySQL query (works as desired):
select id
,json_extract(myJSON, '$**.title2')),0)
from myTable
MySQL ouput:
["b", "d","g","j"]
My problem is that on Redshift I can only specifically define the path as:
JSON_EXTRACT_PATH_TEXT(myJSON, 'master-title2',0,'title')
So I can only get one element instead of all of them.
Any idea how to evaluate all paths and to get all elements in a JSON array which have the same "title2" using Redshift? (same output as in MySQL)
Thank you in advance.
Redshift has only a very rudimentary set to JSON manipulation functions (basically JSON_EXTRACT_PATH_TEXT and JSON_EXTRACT_ARRAY_ELEMENT_TEXT). It's not enough to deal with schemaless JSON.
Python UDF
If Redshift was my only mean of processing data I would give python UDF a try. You can code a function in imperative python. Then, having a column holding your json object and just call that function on all elements to do custom extraction.
Unnesting JSON arrays
Other options would be to really try to understand the schema and implement it using the two JSON funtions mentioned before (This SO answer will give you an idea on how to explode/unnest a JSON array in Redshift). Provided your JSON is not arbitrarily nested, but follows some patterns, this could work.
Regex (better don't)
Another desperate approach would be to try to extract your data with regex - could work for simple cases, but it's an easy way to shoot yourself in the foot.
Thanks for your answer.
I finally found a solution using Python. I hope it may help some others.
count=[x.count("title2") for x in df['myJSON'].tolist()]

Calling from Xtend to Java with multi-dimensional array parameters

I need to call a Java method from Xtend that expects a two dimensional array such as:
javafunc (String [][] {{"0","1"}.{"2","3"}})
My initial thought is to write a Java static method that accepts a List of arrays,
converts it to a two dimensional array and calls the underlying Java method. Before I do this I would like to know if there are better solutions. This one is a bit ugly.
If you want to avoid using arrays, you could use a list of pairs.
#["0" -> "1", "1" -> "2"]
I would convert it using a extension function instead of writing a wrapper for the java function. That way it is more resuable.
javafunc(#["0" -> "1", "1" -> "2"].toArrays)
def String[][] toArrays(Iterable<Pair<String,String>> pairs) {
// convert pairs to 2d array ...
}
Whether this is a good solution depends a bit on what the data represents though, pairs can be confusing if there is no obvious relationship between key and value.

Is this valid JSON? Does root of a JSON stream/file have to be a single object or array?

Is the following valid JSON?
["start", 1234]
["open", 97]
I read the official standard twice and I wasn't able to find anything that said that this isn't valid JSON.
Interesting question. Couldn't help but research a bit. RFC-7159 explicitly refers to ECMA-404, which says:
A JSON value can be an object, array, number, string, true, false, or null
So basically, ECMA-404 tells us that a JSON value can be either of the above, but only a single one of them. Given your example:
["start", 1234]
["open", 97]
That'd not be considered valid JSON together, at it is not an array, but two arrays, and therefore two JSON values and not one.

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.

Postgresql from Json Object to array

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.)