MongoError:当存储由xml2js模块生成的JSON对象时,key $不能以’$’开头

大家,

MongoDB db.version() is 3.0.5
mongodb package.json shows 2.0.42 version
xml2js package.json shows 0.4.9 version  

我已经搜索了错误,并阅读了所有现有的问题,似乎没有一个符合我的情况(jira issue,也不是google group discussions等).这可能与mongodb本机驱动程序(或MongoDB服务器版本),xml2js或其他内容有关.

我做了很多测试,确实找到了解决问题的方法但是,我很想知道问题是什么.

我有一个应用程序执行以下操作:

>将XForm(survey.xml)上传到ExpressJS
>使用xml2js库将XML转换为JSON对象(示例如下所示)
>迭代在2中创建的JSON对象并删除不必要的字段(下面显示的代码段代码)
>使用mongodb本机驱动程序将3中的修改后的JSON对象推送到MongoDB

第4步失败并出现错误(显示在问题标题中).

>有两个JSON对象,一个是调查表单,包含$keys但是,在我将文档插入mongodb之前,我使用以下代码删除了$keys

(function traverse(o) {
for (var i in o) {
  if (o[i] !== null && typeof(o[i])=="object") {
      //going on step down in the object tree!!
    if(o[i].$) {
      var ref = "";
      if(o[i].$.ref) {
        ref = o[i].$.ref;
      } else if (o[i].$.nodeset) {
        ref = o[i].$.nodeset;
      }
      o[i].ref = ref;
      o[i].$= undefined;
      var chunks = ref.split('/');
      o[i]['name'] = chunks[chunks.length - 1];
    }
    traverse(o[i]);
  }
}
})(body);

>我在将其添加到MongoDB之前控制台记录上面的输出,并且console.log没有显示带有$的键的符号.
>假设步骤2由于密钥中的$而实际上失败,这不是真的,我有另一个JSON,它是调查的响应,并且不包含任何$,但是也会失败并出现相同的错误(MongoError:key $不能以“$”开头.

db.collection('submissions').insert(jsonObject, function(err, result) {
  if(err) console.log('error is : ' + err);
  console.log('insertion result : ' + JSON.stringify(result));
});

以下是XML表单提交

   <?xml version='1.0' ?>
   <ppe id="ppe_checklist_new">
    <starting_repeat>
        <location>dark_room</location>
        <ppe_dark>safety_glasses</ppe_dark>
        <xyz_group>
            <condition>condition_missing</condition>
            <test_condition>b</test_condition>
        </xyz_group>
    </starting_repeat>
    <starting_repeat>
        <location>nitrogen_store</location>
        <ppe_nitrogen>leather_gloves_s</ppe_nitrogen>
        <xyz_group>
            <condition>condition_replacing</condition>
            <test_condition />
        </xyz_group>
    </starting_repeat>
    <starting_repeat>
        <location>nitrogen_store</location>
        <ppe_nitrogen>blue_gloves_m</ppe_nitrogen>
        <xyz_group>
            <condition />
            <test_condition>b</test_condition>
        </xyz_group>
    </starting_repeat>
    <starting_repeat>
        <location>cold_room_first</location>
        <ppe_cold>hearing_muff_1</ppe_cold>
        <xyz_group>
            <condition>condition_ok</condition>
            <test_condition>f</test_condition>
        </xyz_group>
    </starting_repeat>
    <sample_group>
        <date>2015-08-24</date>
        <random_number>55</random_number>
    </sample_group>
    <another_group>
        <another_repeat>
            <sample_text>Sample text 1</sample_text>
            <image />
        </another_repeat>
        <another_repeat>
            <sample_text>Sample text 2</sample_text>
            <image />
        </another_repeat>
    </another_group>
    <form_done>OK</form_done>
    <survey_start>2015-08-24T16:55:23.185+01</survey_start>
    <survey_end>2015-08-24T16:57:24.460+01</survey_end>
    <survey_day>2015-08-24</survey_day>
    <survey_device>353490061313389</survey_device>
    <meta>
        <instanceID>uuid:2aba0eff-5350-47e3-9e9c-9606d2c9e7d6</instanceID>
    </meta>
</ppe>

我用以下配置将上面的内容提供给xml2js模块:

function parseXMLToJS(filename, path, callback) {
  var parser = new xml2js.Parser({explicitArray:false});
  var fileURL = path + filename;

  var data = fs.readFile(fileURL, function(err, data) {
    if(err) {
      logger.error('Error reading submission file. Error %', err);
    } else {
      parser.parseString(data, function (err, result) {
        if(err) {
          logger.error('Error parsing XML to JS. Error : %',  err);
          callback({parsed:false, result:result});
        } else {
          callback({parsed:true, result:result});
        }
      });
    }
  });
}

并且模块生成一个JSON对象,如下所示:

{
    "ppe": {
        "starting_repeat": [
            {
                "location": "dark_room",
                "ppe_dark": "safety_glasses",
                "xyz_group": {
                    "condition": "condition_missing",
                    "test_condition": "b"
                }
            },
            {
                "location": "nitrogen_store",
                "ppe_nitrogen": "leather_gloves_s",
                "xyz_group": {
                    "condition": "condition_replacing",
                    "test_condition": ""
                }
            },
            {
                "location": "nitrogen_store",
                "ppe_nitrogen": "blue_gloves_m",
                "xyz_group": {
                    "condition": "",
                    "test_condition": "b"
                }
            },
            {
                "location": "cold_room_first",
                "ppe_cold": "hearing_muff_1",
                "xyz_group": {
                    "condition": "condition_ok",
                    "test_condition": "f"
                }
            }
        ],
        "sample_group": {
            "date": "2015-08-24",
            "random_number": "55"
        },
        "another_group": {
            "another_repeat": [
                {
                    "sample_text": "Sample text 1",
                    "image": ""
                },
                {
                    "sample_text": "Sample text 2",
                    "image": ""
                }
            ]
        },
        "form_done": "OK",
        "survey_start": "2015-08-24T16:55:23.185+01",
        "survey_end": "2015-08-24T16:57:24.460+01",
        "survey_day": "2015-08-24",
        "survey_device": "353490061313389",
        "id": "ppe_checklist_new",
        "uuid": "2aba0eff-5350-47e3-9e9c-9606d2c9e7d6"
    }
}

我试着检查我插入MongoDB的数据是否是对象,结果证明它是.

typeof(result.result)

>尝试通过Mongo Shell从xml2js插入生成的JSON对象,它工作正常.
>尝试在我的javascript代码中创建一个JS对象,其内容与xml2js生成的JSON相同,并通过mongodb本机驱动程序将其插入到MongoDB中(尽管我比较了两个JSON并且它们完全相同).

总之,我可以说mongodb本机驱动程序不喜欢xml2js模块生成的JSON对象,为什么我不知道?我等不及要知道了.我尝试了以下方法来解决

>使用xml2js转换XML 2 JSON
>从xml2js中对返回的JSON对象进行字符串化(x = JSON.stringify(obj);)
>解析了字符串化的JSON对象(parsedX = JSON.parse(x);)
>通过mongodb本机驱动将已解析的值插入MongoDB,并且它有效.

无论出现什么问题,上述错误消息都有点误导或可能不适合导致此问题的问题.我找不到一种方法来获得更详细的错误(也许有一种方法可以让mongodb提供更多解释,很想知道).

感谢您的时间和耐心.

最佳答案 遍历函数的以下行只是将$字段设置为undefined值而不实际删除它.

o[i].$= undefined;

将该行更改为使用delete删除它:

delete o[i].$;

使用JSON.stringify和JSON.parse的解决方法有效,因为未定义的值无法用JSON表示,因此JSON.stringify调用会删除具有该值的字段.

点赞