如何解析json关键点文字

时间:2018-04-24 13:57:34

标签: javascript json

我有这个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"
}

5 个答案:

答案 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;
&#13;
&#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));