[英]Convert nested array of array to nested array of object
我目前面临转换以下数据的挑战:
{
"fieldname1": "value",
"fieldname3": [
"value 1",
[
[
"firstname",
"lastname"
]
]
],
"fieldname2": [
[
[
"value 3"
],
"full name"
]
]
}
进入以下:
{
"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"
}
]
}
我目前有点迷失如何将源数据转换为预期的 object。
我从 sql 查询( presto )中获取数据。
结构化信息( fieldname2
和fieldname3
)未解析,我只得到响应中的值。
根级别的字段 position 是动态的(可以是fieldname1
, fieldname2
, fieldname3
也可以是fieldname3
, fieldname1
, fieldname2
)。
fieldname2
和fieldname3
中的值 position 似乎是 static。
我已经解决了将给定表模式转换为 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
}
基于 JSONSchema,我能够生成将在代码生成器中使用的“模型定义”:
{
"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
}
}
}
}
根据@nikhil 的评论,我花了一个小时来创建一个运行原型。
我已经用提供的示例数据和真实数据成功地测试了它。
它在两种情况下都有效。
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))
我希望我理解得足够充分。 尝试使用 array.group() 方法:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/group
祝你好运!!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.