How do I convert a flat table into a JSON?
I have previously converted JSONs into Flat Tables using both custom code and libraries. However, what I am aiming to do here is the reverse. Before going ahead and creating a custom library, I was wondering if anyone had encountered this problem before and if there was an existing solution to it.
When you flatten a JSON into a CSV, you loose the information on the structure, and therefore to reverse it, you need a document that describes how the JSON should be built, which ideally would be the standardised JSON Schema.
The following example shows a source CSV, the JSON Schema and the expected output.
User CSV
user_id, adress.city, address.street, address.number, name, aka, contacts.name, contacts.relationship
1, Seattle, Atomic Street, 6910, Rick Sanchez, Rick, Morty, Grandson
1, Seattle, Atomic Street, 6910, Rick Sanchez, Grandpa, Morty, Grandson
1, Seattle, Atomic Street, 6910, Rick Sanchez, Albert Ein-douche, Morty, Grandson
1, Seattle, Atomic Street, 6910, Rick Sanchez, Richard, Morty, Grandson
1, Seattle, Atomic Street, 6910, Rick Sanchez, Rick, Beth, Daughter
1, Seattle, Atomic Street, 6910, Rick Sanchez, Grandpa, Beth, Daughter
1, Seattle, Atomic Street, 6910, Rick Sanchez, Albert Ein-douche, Beth, Daughter
1, Seattle, Atomic Street, 6910, Rick Sanchez, Richard, Beth, Daughter
JSON Schema
This follows the defined standard with the addition of the "source" property. I am suggesting adding this custom property to this specific problem in order to map between the csv columns and the JSON values (leafs).
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "User",
"type": "object",
"properties":{
"user_id" : {"type":"integer", "source":"user_id"},
"address":{
"type":"object",
"properties":{
"city" : {"type":"string", "source":"adress.city"},
"street" : {"type":"string", "source":"adress.street"},
"number": { "type":"integer", "source":"adress.number"}
}
},
"name" : {"type":"string", "source":"name"}},
"aka":{
"type": "array",
"items" : {"type":"string", "source":"aka"}
},
"contacts":{
"type":"array",
"items":{
"type":"object",
"properties":{
"name" : {"type":"string", "source":"contacts.name"},
"relationship":{"type":"string", "source":"contacts.relationship"}
},
}
}
}
}
Expected JSON
{
"user_id":1,
"address":{
"city":"Seattle",
"street":"Atomic Street",
"number":6910
},
"name":"Rick Sanchez",
"aka":[
"Rick",
"Grandpa",
"Albert Ein-douche",
"Richard"
],
"contacts":[
{
"name":"Morty",
"relationship":"Grandson"
},
{
"name":"Beth",
"relationship":"Daughter"
}
]
}
From the above we see that although there are 8 rows in the CSV, we are producing a single JSON Object (instead of 8) since there is only one unique user (user_id = 1). This could be inferred from the JSON Schema where the root element is an object and not a list.
If we did not specify a JSON Schema or other kind of mapping, you could simply assume no structure and just create 8 flat jsons as below
[
{"user_id":1,"address.city":"Seattle", ... "aka":"Rick" ... "contacts.relationship":"Grandson"}
...
{"user_id":1,"address.city":"Seattle", ... "aka":"Richard" ... "contacts.relationship":"Daughter"}
]
I am adding the Python tag since that is the language I use mostly, but in this case, the solution doesn't need to be in Python.