javascript - How to parse json key dot literals - Stack Overflow

I have this JSON object, it's a dynamically generated object, I can't control how it's f

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
Add a ment  | 

5 Answers 5

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

相关推荐

  • javascript - How to parse json key dot literals - Stack Overflow

    I have this JSON object, it's a dynamically generated object, I can't control how it's f

    8天前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信