How to Convert Julia Dictionary Keys from Strings to Integer - json

I want to convert Julia Dictionary Keys that are Strings to Integers
JSON3 converts the keys of my Dictionary into Strings. My understanding is that JSON keys are only strings.
using JSON3
a1 = Dict(1 => "one", 2 => "two", 3 => "three")
a1_json = JSON3.write(a1)
"{\"2\":\"two\",\"3\":\"three\",\"1\":\"one\"}"
a2 = JSON3.read(json,Dict{Int64,String})
ERROR: MethodError: no method matching Int64(::String)
Is there any way to keep the keys in Int?

from JSON3.jl readme:
Declaring my type is JSON3.ObjectType() means it should map to a JSON object of >unordered key-value pairs, where keys are Symbol or String, and values are any other type (or Any).
So, in the parse step, you are gonna get symbols if you use numbers as keys.
with that said, you can use this code to recover the original dict:
Dict(parse(Int,string(k))=>v for (k,v) in pairs(a2))

Related

Kotlin serialization module. How to serialize/deserialize a plain json field?

I have an object with the following structure:
enum class GeometryType { ... }
data class GeometryItem(
val type: GeometryType,
val geomtryJson: String
)
Where an example json could be:
{
type: "Point",
geometryJson: [12.0, 11.0]
}
So gemetryJson is a valid json string, but not quoted.
Could this be accomplished using Kotlin Serialization module?
According to JSON RFC:
A JSON value MUST be an object, array, number, or string, or one of
the following three literal names: false null true.
The representation of strings is similar to conventions used in the C
family of programming languages. A string begins and ends with
quotation marks.
An array structure is represented as square brackets surrounding
zero or more values (or elements). Elements are separated by
commas.
So the value of geometryJson: [12.0, 11.0] has array type, not a string type.
As for kotlinx-serialization out of the box it won't handle such deserialization. You can try to write your own decoder, but I would suggest to use Jackson library for this task. Not a full solution:
val mapper = jacksonObjectMapper()
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true)
val json ="""
{
type: "POINT",
geometryJson: "[12.0, 11.0]"
}
""".trimIndent()
val geometryItem = mapper.readValue<GeometryItem>(json)
println("geometryItem = $geometryItem")
With such config you can handle at least unquoted json fields.
As for reading array values I would suggest to read it to array of doubles, and if you need to represent it as string use such conversion:
val stringArray = doubleArray.map { it.toString() }.toTypedArray().contentToString()

How can I use a json file if all elements are in one array?

I'm trying to learn to import JSON files into p5.js.
I'm using this list of English words: https://raw.githubusercontent.com/dwyl/english-words/master/words_dictionary.json
I already know how to import things when the entries are organized into respective categories. It seems every entry is in the same array, though. How can I import individual entries?
In this particular case the data you're loading isn't a regular array ([]) with values accessed using an integer index, but a JavaScript Object or associative array({}) with values accessed using a string instead of an integer index.
This is a key-value pair association.
Let's say you have a simple association:
let data = {
"firstName": "Nicholas",
"lastName": "Keough",
}
In the example above firstName and lastName are keys and "Nicholas" and "Keough" are values.
You can use array like [] and instead of an integer index, you'd use the key:
console.log(data["firstName"]);// prints "Nicholas"
console.log(data["lastName"]);// prints "Keough"
alternatively you can use dot notation:
console.log(data.firstName);// prints "Nicholas"
console.log(data.lastName);// prints "Keough"
In your case, let's say dictionary is a variable that holds the loaded JSON data,
you apply the same ideas above to access each word. For example:
console.log(data['absorbent']);//prints 1
or
console.log(data.absorbent.);//prints 1
If you need to loop over the values (and in your case, with the dictionary of 370101 values, you would really want to), you can use a for...in loop.
Alternatively, if you simply need to access the keys, not the values, as a single array you can use Object.keys()
Here's a basic example illustrating both options:
(Bare in mind the dictionary is large so it will take time to load and print the data to console)
let dictionary;
// preload JSON data
function preload(){
dictionary = loadJSON("https://raw.githubusercontent.com/dwyl/english-words/master/words_dictionary.json");
}
function setup(){
noLoop();
console.log('test');
// access JSON data with a for...in loop
for(let word in dictionary){
console.log("word: " + word + " value: " + dictionary[word]);
}
// optionally, access the associative array keys only as an array
console.log(Object.keys(dictionary));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>

I need parse JSON to Greenplum

How to parse JSON
{
"35673": [
"234",
"357",
"123"
],
"34566": [
"333",
"456",
"789"
]
}
to Greenplum table, format 1 key 1 value?
In your basic example, there is no json nested object, no array of json object, and all the object values are arrays of string. So within these assumptions, you can use the json_path_query function with the jsonpath operator keyvalue() so that to split your json object into a set of key/value and then use the json_array_elements function so that to split the resulting values which are systematically 1-Dim arrays :
SELECT j->>'key' AS Key, json_array_elements(j->'value')->>0 AS Value
FROM json_path_query (your_json_object_here, '$.keyvalue()') AS j
The output for your example is :
Key Value
34566 333
34566 456
34566 789
35673 234
35673 357
35673 123
All these functions can apply to the jsonb type which is preferred to the json type, see the manual :
"The json and jsonb data types accept almost identical sets of values as input. The major practical difference is one of efficiency. The
json data type stores an exact copy of the input text, which
processing functions must reparse on each execution; while jsonb data
is stored in a decomposed binary format that makes it slightly slower
to input due to added conversion overhead, but significantly faster to
process, since no reparsing is needed. jsonb also supports indexing,
which can be a significant advantage."
If your json structure is more complex with nested objects or arrays of objects, you will have to adapt the function in the FROM clause.
If your object values are not systematically arrays of string, you will have to adapt the function applied to the resulting json value field.

KDB: How to parse a json file?

I created a config file in JSON format, and I want to use KDB to read it in as a dictionary.
In Python, it's so easy:
with open('data.json') as f:
data = json.load(f)
Is there a similar function in KDB?
To read your JSON file into kdb+, you should use read0. This returns the lines of the file as a list of strings.
q)read0`:sample.json
,"{"
"\"name\":\"John\","
"\"age\":30,"
"\"cars\":[ \"Ford\", \"BMW\", \"Fiat\" ]"
,"}"
kdb+ allows for the de-serialisation (and serialisation) of JSON objects to dictionaries using the .j namespace. The inbuilt .j.k expects a single string of characters containing json and converts this into a dictionary. A raze should be used to flatten our list of strings:
q)raze read0`:sample.json
"{\"name\":\"John\",\"age\":30,\"cars\":[ \"Ford\", \"BMW\", \"Fiat\" ]}"
Finally, using .j.k on this string yields the dictionary
q).j.k raze read0`:sample.json
name| "John"
age | 30f
cars| ("Ford";"BMW";"Fiat")
For a particularly large JSON file, it may be more efficient to use read1 rather than raze read0 on your file, e.g.
q).j.k read1`:sample.json
name| "John"
age | 30f
cars| ("Ford";"BMW";"Fiat")
If you're interested in the reverse operation, you can use .j.j to convert a dictionary into a list of strings and use 0: to save.
Further information on the .j namespace can be found here.
You can also see more examples on the Kx wiki of read0, read1 and 0:.
Working with JSON is handled by the .j namespace where .j.j serialises and .j.k deserialises the messages. Note the you will need to use raze to convert the JSON into a single string first.
There is more information available on the Kx wiki, where the following example is presented:
q).j.k "{\"a\":[0,1],\"b\":[\"hello\",\"world\"]}"
a| 0 1
b| "hello" "world"
When using .j.j both symbols and strings in kdb will be encoded into a JSON string while kdb will decode JSON strings to kdb strings except keys where they will be symbols.
To encode a kdb table in JSON an array of objects with identical keys should be sent. kdb will also encode tables as arrays of objects in JSON.
q).j.k "[{\"a\":1,\"b\":2},{\"a\":3,\"b\":4}]"
a b
---
1 2
3 4
When encoding q will use the value of \P to choose the precision, which is by default 7 which could lead to unwanted rounding.
This can be changed with 0 meaning maximum precision although the final digits are unreliable as shown below. See here for more info https://code.kx.com/q/ref/cmdline/#-p-display-precision.
q).j.j 1.000001 1.0000001f
"[1.000001,1]"
q)\P 0
q).j.j 1.000001 1.0000001f
"[1.0000009999999999,1.0000001000000001]"

How do I deserialize a JSON array using the Play API

I have a string that is a Json array of two objects.
> val ss = """[ {"key1" :"value1"}, {"key2":"value2"}]"""
I want to use the Play Json libraries to deserialize it and create a map from the key values to the objects.
def deserializeJsonArray(ss:String):Map[String, JsValue] = ???
// Returns Map("value1" -> {"key1" :"value1"}, "value2" -> {"key2" :"value2"})
How do I write the deserializeJsonArray function? This seems like it should be easy, but I can't figure it out from either the Play documentation or the REPL.
I'm a bit rusty, so please forgive the mess. Perhaps another overflower can come in here and clean it up for me.
This solution assumes that the JSON is an array of objects, and each of the objects contains exactly one key-value pair. I would highly recommend spicing it up with some error handling and/or pattern matching to validate the parsed JSON string.
def deserializeJsonArray(ss: String): Map[String, JsValue] = {
val jsObjectSeq: Seq[JsObject] = Json.parse(ss).as[Seq[JsObject]]
val jsValueSeq: Seq[JsValue] = Json.parse(ss).as[Seq[JsValue]]
val keys: Seq[String] = jsObjectSeq.map(json => json.keys.head)
(keys zip jsValueSeq).toMap
}