我有这个JSON对象,它是一个动态生成的对象,我无法控制它如何格式化为json。问题是json看起来像这样:
{
"id": "def",
"name": "def",
"description": {},
"description.shortened": "def",
"description.extended": "def",
"type": "EDIBLE_BOUQUET",
"image": {},
"image.name": "def",
"image.slug": "def",
"image.extension": "PNG",
"state": "FEATURED",
"stock": "def"
}
我将如何将其转换为:
{
"id": "def",
"name": "def",
"description": {
"shortened": "def",
"extended": "def"
},
"type": "EDIBLE_BOUQUET",
"image": {
"name": "def",
"slug": "def",
"extension": "PNG"
},
"state": "FEATURED",
"stock": "def"
}
答案 0 :(得分:1)
迭代对象的键,并对其进行转换。
function transform(obj){
let tmp={}
Object.keys(obj).forEach(k=>{
if(k.includes('.')){
let path=k.split('.')
let x=path.pop()
path.reduce((cur,p)=>{
if(!(p in cur))cur[p]={}
return cur[p]
},tmp)[x]=obj[k]
}
else{
tmp[k]=obj[k]
}
})
return tmp
}
const obj={
a: 1,
'b.c.d': 2
}
console.log(transform(obj)) // {a: 1, b: {c: {d: 2}}}

答案 1 :(得分:1)
如果您正在使用lodash,_.set
完全按照您在此处尝试的操作:
const source = {"id":"def","name":"def","description":{},"description.shortened":"def","description.extended":"def","type":"EDIBLE_BOUQUET","image":{},"image.name":"def","image.slug":"def","image.extension":"PNG","state":"FEATURED","stock":"def"};
let target = {};
Object.keys(source).forEach(key => {
_.set(target, key, source[key]);
});
console.log(target);

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
&#13;
只有一个catch,parent属性应始终位于源对象中的子属性之前,即description
应出现在description.shortened
之前。
答案 2 :(得分:1)
使用lodash的set
方法将是最简单的方法。
const json = '{"id": "def","name": "def","description": {},"description.shortened": "def","description.extended": "def","type": "EDIBLE_BOUQUET","image": {},"image.name": "def","image.slug": "def","image.extension": "PNG","state": "FEATURED","stock": "def"}';
const obj = JSON.parse(json);
const newObj = Object.keys(obj).reduce((o, k) => _.set(o, k, obj[k]), {});
console.log(newObj);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script>
应注意的是,如果不保证对象键处于所示顺序,则某些数据可能会丢失。请参阅以下示例。
const json = '{"id": "def","name": "def","description.shortened": "def","description.extended": "def","description": {},"type": "EDIBLE_BOUQUET","image": {},"image.name": "def","image.slug": "def","image.extension": "PNG","state": "FEATURED","stock": "def"}';
const obj = JSON.parse(json);
const newObj = Object.keys(obj).reduce((o, k) => _.set(o, k, obj[k]), {});
console.log(newObj);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script>
由于set
方法按照keys
方法提供的顺序迭代键,因此最后一个键将值设置为提供的值。因此,如果description: {}
对跟随任何先前的description.x: y
对,那么一旦分配了空对象,这些值就会丢失。
一个简单的修复方法是包含一个sort
来强制空对象对作为第一个提供的密钥。但请注意,这也会导致对象的其余部分不再与原始对象的顺序相同。
const json = '{"id": "def","name": "def","description.shortened": "def","description.extended": "def","description": {},"type": "EDIBLE_BOUQUET","image": {},"image.name": "def","image.slug": "def","image.extension": "PNG","state": "FEATURED","stock": "def"}';
const obj = JSON.parse(json);
const newObj = Object.keys(obj).sort().reduce((o, k) => _.set(o, k, obj[k]), {});
console.log(newObj);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script>
如果您确实需要自己滚动,那么以下内容就足够了:
const json = '{"id": "def","name": "def","description.shortened": "def","description.extended": "def","description": {},"type": "EDIBLE_BOUQUET","image": {},"image.name": "def","image.slug": "def","image.extension": "PNG","state": "FEATURED","stock": "def"}';
const obj = JSON.parse(json);
const newObj = Object.keys(obj).sort().reduce((o, k) => {
const paths = k.split('.');
// Get to currently defined depth of object
let depth = 0;
let oRef = o;
while (oRef.hasOwnProperty(paths[depth])) {
oRef = oRef[paths[depth++]];
}
const val = paths.slice(depth).reduceRight((v, p) => ({[p]: v}), obj[k]);
Object.assign(oRef, val);
return o;
}, {});
console.log(newObj);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script>
答案 3 :(得分:1)
相当直接。
检查每个属性以查看名称是否包含.
,添加正确的属性并删除原始属性。
const src = {
"id": "def",
"name": "def",
"description": {},
"description.shortened": "def",
"description.extended": "def",
"type": "EDIBLE_BOUQUET",
"image": {},
"image.name": "def",
"image.slug": "def",
"image.extension": "PNG",
"state": "FEATURED",
"stock": "def"
};
for (var k in src) {
let index = k.indexOf('.');
if (index > 0){
let [base, prop] = k.split('.');
let value = src[k];
delete src[k]
src[base][prop] = value;
}
}
console.log(src)
答案 4 :(得分:1)
let obj = {
"id": "def",
"name": "def",
"description": {},
"description.shortened": "def",
"description.extended": "def",
"type": "EDIBLE_BOUQUET",
"image": {},
"image.name": "def",
"image.slug": "def",
"image.extension": "PNG",
"state": "FEATURED",
"stock": "def"
}
const transformObj = obj => {
return Object.keys(obj).reduce((acc, key) => {
if(key.indexOf('.') >= 0){
const [parentKey, childKey] = key.split('.');
acc[parentKey] = acc[parentKey] || {};
acc[parentKey][childKey] = obj[key];
} else {
acc[key] = obj[key];
}
return acc;
}, {});
}
console.log(transformObj(obj));