I have currently the challenge to convert the following data:
{
"fieldname1": "value",
"fieldname3": [
"value 1",
[
[
"firstname",
"lastname"
]
]
],
"fieldname2": [
[
[
"value 3"
],
"full name"
]
]
}
into the following:
{
"fieldname1": "value",
"fieldname3": {
"field3_sub1": "value 1",
"field3_sub2": [
{
"field3_sub2_1": "firstname",
"field3_sub2_2": "lastname"
}
]
},
"fieldname2": [
{
"field2_sub1": [
"value 3"
],
"field2_sub2": "full name"
}
]
}
I'm currently a bit lost how I could convert the source data into the expected object.
I get the data from a sql query ( presto ).
The structured information ( fieldname2
and fieldname3
) aren't resolved, I get only the values in the response.
The field position at root level is dynamic ( could be fieldname1
, fieldname2
, fieldname3
but also fieldname3
, fieldname1
, fieldname2
).
The value position inside fieldname2
and fieldname3
seems to be static.
I already solved the challenge to convert the given table schema into a JSONSchema:
{
"type": "object",
"properties": {
"fieldname2": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field2_sub1": {
"type": "array",
"items": {
"type": "string"
}
},
"field2_sub2": {
"type": "string"
}
},
"additionalProperties": false,
"title": "fieldname2"
}
},
"fieldname1": {
"type": "string"
},
"fieldname3": {
"type": "object",
"properties": {
"field3_sub1": {
"type": "string"
},
"field3_sub2": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field3_sub2_1": {
"type": "string"
},
"field3_sub2_2": {
"type": "string"
},
},
"additionalProperties": false,
"title": "field3_sub2"
}
}
},
"additionalProperties": false,
"title": "fieldname3"
}
},
"additionalProperties": false
}
Based on the JSONSchema I was able to generate a "model definition" which will be used in a code generator:
{
"Fieldname2": {
"root": false,
"fields": {
"field2_sub1": {
"name": "field2_sub1",
"fieldType": "string[]",
"graphqlType": "[String]",
"nullable": true,
"filter": false
},
"field2_sub2": {
"name": "field2_sub2",
"fieldType": "string",
"graphqlType": "String",
"nullable": true,
"filter": true
}
}
},
"Field3_sub2": {
"root": false,
"fields": {
"field3_sub2_1": {
"name": "field3_sub2_1",
"fieldType": "string",
"graphqlType": "String",
"nullable": true,
"filter": true
},
"field3_sub2_2": {
"name": "field3_sub2_2",
"fieldType": "string",
"graphqlType": "String",
"nullable": true,
"filter": true
}
}
},
"Fieldname3": {
"root": false,
"fields": {
"field3_sub1": {
"name": "field3_sub1",
"fieldType": "string",
"graphqlType": "String",
"nullable": true,
"filter": true
},
"field3_sub2": {
"name": "field3_sub2",
"fieldType": "Field3_sub2[]",
"graphqlType": "[Field3_sub2]",
"nullable": true,
"filter": false
}
}
},
"Record": {
"root": true,
"fields": {
"fieldname2": {
"name": "fieldname2",
"fieldType": "Fieldname2[]",
"graphqlType": "[Fieldname2]",
"nullable": true,
"filter": false
},
"fieldname1": {
"name": "fieldname1",
"fieldType": "string",
"graphqlType": "String",
"nullable": true,
"filter": true
},
"fieldname3": {
"name": "fieldname3",
"fieldType": "Fieldname3",
"graphqlType": "Fieldname3",
"nullable": true,
"filter": false
}
}
}
}
CodePudding user response:
Based on the comment from @nikhil, I spent an hour to create a running prototype.
I have tested it successfully with the provided example data and real data.
It worked in both cases.
const transformObject = (data, definition) => {
let res = {};
// get the field names from the definition
const definitionFields = Object.keys(definition);
for (let iElement = 0; iElement < data.length; iElement ) {
// get the current property name
const propName = definitionFields[ iElement ]
// get the definition for the current field
const fieldDefinition = definition[ propName ];
// in case the current value is a simple type, return it
if (fieldDefinition.type !== "array" && fieldDefinition.type !== "object") {
res[ propName ] = data[ iElement ];
}
// if the expected value for the current property is an object,
// run the object transformation
if (fieldDefinition.type === "object") {
res[ propName ] = transformObject(
data[ iElement ],
fieldDefinition.properties
);
}
// if the expected value for the current property is an array,
// run the array transformation
if (fieldDefinition.type === "array") {
res[ propName ] = transformArray(
data[ iElement ],
fieldDefinition.items
);
}
}
return res;
};
const transformArray = (data, definition) => {
// in case we have a simple type like string, number, etc.
// use the given data as return value
if (definition.type !== "object") {
return data;
}
// otherwise run the transform object function
// to generate the key/value pair
// NOTE: Since I don't have array of arrays in my usecase
// I didn't implemented the check for arrays
// i assume that the return value should be always
// an array of object or array of string/number/boolean
return data.map((ele) => {
return transformObject(ele, definition.properties);
});
};
const transform = (data, definition) => {
let res = {};
for (const [ key, value ] of Object.entries(data)) {
// get the current field definition from the schema
const fieldDefinition = definition[ key ];
// for simple types like string, number, etc. we don't have
// to run a transformation, just return the given value
if (fieldDefinition.type !== "object" && fieldDefinition.type !== "array") {
res[ key ] = value;
}
// in case of an object, run the object transformation
if (fieldDefinition.type === "object") {
res[ key ] = transformObject(value, fieldDefinition.properties);
}
// in case of an array, run the array transformation
if (fieldDefinition.type === "array") {
res[ key ] = transformArray(value, fieldDefinition.items);
}
}
return res;
};
const source = {
/**
* The provided data from the question
*/
}
const schema = {
/**
* the provided JSONSchema from the question
*/
}
const transformed = transform(source, schema.properties);
console.log(JSON.stringify(transformed, null, 2))
CodePudding user response:
I hope I understood pretty enough. Try playing with the array.group() method:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/group
Good luck!!