如何将JSON对象结构转换为点符号表示法?

13

我有一个变量存储,它将决定从查询中排除哪些字段:

excludeFields = {
  Contact: {
    Address: 0,
    Phone: 0
  }
}

我需要将这个转换为点表示法,以便与Mongo的findOne一起使用,例如:

things.findOne({}, {fields: {'Contact.Address': 0, 'Contact.Phone': 0}})

仅传递 excludeFields 是不起作用的,会导致错误 "Projection values should be one of 1, 0, true, or false"

things.findOne({}, {fields: excludeFields})

我是否需要编写自己的函数将分层结构转换为平面点符号表示法?还是JavaScript中有一些我不知道的机制可以实现这一点?

3个回答

28

这应该足够灵活以满足大多数需求:

function dotNotate(obj,target,prefix) {
  target = target || {},
  prefix = prefix || "";

  Object.keys(obj).forEach(function(key) {
    if ( typeof(obj[key]) === "object" && obj[key] !== null ) {
      dotNotate(obj[key],target,prefix + key + ".");
    } else {
      return target[prefix + key] = obj[key];
    }
  });

  return target;
}

像这样在您的excludesFields变量上运行:

dotNotate(excludeFields);

它返回当前结构:

{ "Contact.Address" : 0, "Contact.Phone" : 0 }

所以,你甚至可以内联地实现:

things.findOne({}, {fields: dotNotate(excludeFields) })

或者作为投影提供:

var projection = { "fields": {} };
dotNotate(excludeFields,projection.fields);
things.findOne({}, projection);

在所有深度上都能良好地运作,即使使用数组也是必要的方式,除非您需要像$push这样的操作符。


在JavaScript中,null值也被视为对象。 - Ravinder Payal
这将跳过日期对象:您可以添加一个单独的检查,例如 typeof(val) === "object" && val !== null && !(val instanceof Date) - Philipp Sumi

3

我使用的函数与被接受的答案非常相似。

    function convertJsonToDot(obj, parent = [], keyValue = {}) {
      for (let key in obj) {
        let keyPath = [...parent, key];
        if (obj[key]!== null && typeof obj[key] === 'object') {
            Object.assign(keyValue, convertJsonToDot(obj[key], keyPath, keyValue));
        } else {
            keyValue[keyPath.join('.')] = obj[key];
        }
    }
    return keyValue;
}

在这里,我进行了一个额外的检查'obj[key] !== null',因为不幸的是null也是'type'对象。

实际上我想把这个作为对已接受答案的评论添加,但是由于声望不足而不能添加。


为了清晰起见,最好明确写出 obj[key] !== null 而不仅仅检查 obj[key] 是否为真值。 - cdimitroulas
1
同意。我编辑了我的答案。 - Murali Raju
我知道这很老了,但如果您对数组进行操作,则会将其转换为点符号表示法。如果您将其保存到Mongo中而没有数组可供保存,则它会像对象一样保存。 - Ihsan Müjdeci
这将跳过日期对象:您可以添加一个单独的检查,例如 typeof(val) === "object" && val !== null && !(val instanceof Date) - Philipp Sumi

1
var fields = {};
for (var k in excludeFields) {
  for (var p in excludeFields[k]) {
    fields[k + '.' + p] = excludeFields[k][p];
  }
}

然后:

things.findOne({}, {fields: fields})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接