I have this JSON object, it's a dynamically generated object, I can't control how it's formatted to json. The problem is that the json looks like this:
{
"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"
}
How would I go about transforming it into:
{
"id": "def",
"name": "def",
"description": {
"shortened": "def",
"extended": "def"
},
"type": "EDIBLE_BOUQUET",
"image": {
"name": "def",
"slug": "def",
"extension": "PNG"
},
"state": "FEATURED",
"stock": "def"
}
I have this JSON object, it's a dynamically generated object, I can't control how it's formatted to json. The problem is that the json looks like this:
{
"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"
}
How would I go about transforming it into:
{
"id": "def",
"name": "def",
"description": {
"shortened": "def",
"extended": "def"
},
"type": "EDIBLE_BOUQUET",
"image": {
"name": "def",
"slug": "def",
"extension": "PNG"
},
"state": "FEATURED",
"stock": "def"
}
Share
Improve this question
asked Apr 24, 2018 at 13:57
Ryan S.Ryan S.
1343 silver badges9 bronze badges
1
-
1
Use
JSON.parse
and then Create nested Object based on String Properties separated by Periods. – str Commented Apr 24, 2018 at 14:02
5 Answers
Reset to default 4
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));
Iterate through the keys of object, and transform it.
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}}}
If you're in for using lodash, _.set
does exactly what you're trying to do here:
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./ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
Just one catch, the parent property should always be before the child properties in your source object, i.e. description
should occur before description.shortened
.
Fairly straight forward.
Check each property to see if the name contains a .
, add the correct property and delete the original.
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)
Using lodash's set
method would be the easiest path.
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/npm/[email protected]/lodash.min.js"></script>
A concern should be noted that if the object keys are not guaranteed to be in the order shown, some data may be lost. See the following example.
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/npm/[email protected]/lodash.min.js"></script>
Since the set
method iterates over the keys in the order provided from the keys
method, the last key will set the value to whatever is provided. So, if the description: {}
pair follows any previous description.x: y
pair then those values will be lost once the empty object is assigned.
A simple fix would be to include a sort
to force the empty object pair to be the first key provided. Note however this will also cause the rest of the object to no longer be in the same order as the original.
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/npm/[email protected]/lodash.min.js"></script>
If you do need to roll your own then something like the following would suffice:
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/npm/[email protected]/lodash.min.js"></script>
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744115669a4559162.html
评论列表(0条)