【问题标题】:Invalid UTF-8 JSON on CouchDB bulk document apiCouchDB 批量文档 API 上的 UTF-8 JSON 无效
【发布时间】:2012-11-01 04:10:56
【问题描述】:

我有一个节点控制台应用程序,我试图将一些记录发布到本地 CouchDB 实例上的批量文档 api 并获得“无效的 UTF-8 JSON”。让这特别奇怪的是,我在对象文字上使用 JSON.stringify 生成我的 JSON。

我在http://jsonlint.com/ 测试了实际的 json,据说它是有效的。我无法在此处发布完整的 json,因为它是目录中的名称和编号,但我可以向您展示一个模拟记录,以便为您提供基本结构。

{
 "family" : "Smith",
        "people":{
            "Bob":{
                 "name":"Bob", 
                 "active" : true,
                "birthday" : "1/01"
            },
            "Sue":{
                "name": "Sue", 
                "active" : true,
                "birthday" : "1/01"
            }
        },
        "address": {
            "street" :"1111 Cool Road",
            "city" : "Cincinnati",
            "state" : "OH",
            "zip" : "11111"
        },
        "phone" : "923-4908"            
};

我将我的记录数组包装在一个 json 对象中,该对象具有指定的属性“docs”here。我正在尝试做的事情有什么明显的错误吗?

更新: 按照lammmj 的建议,我将node 生成的字符串写入文件,然后使用curl 将其发布到批量文档上传。那工作得很好。不过,我仍然希望有人帮助我更正我的节点代码,以便它在节点内工作。这是构建和发布请求的确切代码

  //The result variable is my array of 'family' objects, 
  //It's generated by parsing a text file, not show here
  var postOptions = {
  host: 'localhost',
  port: '5984',
  path: '/members/_bulk_docs',
  method: 'POST',
  headers: {
      'Content-Type': 'application/json',
      'Content-Length': result.length
  }
};
var request = http.request(postOptions, function(res){
    res.setEncoding('utf8');
    res.on('data', function (chunk) {
      console.log('Response: ' + chunk);
    });
});
var body = { "docs": result};
var stringData = JSON.stringify(body);
console.log(stringData);
request.write(stringData);

【问题讨论】:

    标签: json node.js couchdb


    【解决方案1】:

    我能够使用以下命令让您的示例正常工作:

    curl -X POST -H "Content-type:application/json" \
        http://localhost:5984/test/_bulk_docs -d @family.json
    

    其中family.json 包含以下内容。我添加了第二个族,这样数组中就会有多个元素。

    {"docs": [
      {"family" : "Smith",
        "people":{
            "Bob":{
                 "name":"Bob", 
                 "active" : true,
                "birthday" : "1/01"
            },
            "Sue":{
                "name": "Sue", 
                "active" : true,
                "birthday" : "1/01"
            }
        },
        "address": {
            "street" :"1111 Cool Road",
            "city" : "Cincinnati",
            "state" : "OH",
            "zip" : "11111"
        },
        "phone" : "923-4908"
      },
      {"family" : "Jones",
        "people":{
            "John":{
                 "name":"John",
                 "active" : true,
                "birthday" : "1/01"
            },
            "Mary":{
                "name": "Mary",
                "active" : true,
                "birthday" : "1/01"
            }
        },
        "address": {
            "street" :"1112 Cool Road",
            "city" : "Cincinnati",
            "state" : "OH",
            "zip" : "11111"
        },
        "phone" : "923-4909"
      }
    ]}
    

    JSON 与包装在数组中的提供的相同,并作为传递给 CouchDB 的 JSON 的 docs 属性的值提供。在您给出的示例中还有一个尾随分号 (;)。如果其他所有内容的格式正确,这可能就是问题所在。

    更新:

    好的,这是应答节点代码。我按照代码中的说明进行了 3 处更改:

    #!/usr/bin/env node
    
    var http = require("http");
    
    // Embedding the family object here so that this test program will compile/run.
    
    result = {
         "family" : "Smith",
                "people":{
                    "Bob":{
                         "name":"Bob",
                         "active" : true,
                        "birthday" : "1/01"
                    },
                    "Sue":{
                        "name": "Sue",
                        "active" : true,
                        "birthday" : "1/01"
                    }
                },
                "address": {
                    "street" :"1111 Cool Road",
                    "city" : "Cincinnati",
                    "state" : "OH",
                    "zip" : "11111"
                },
                "phone" : "923-4908"        
        };
    
    var body = { "docs": [result]};                 // Change #1: docs takes an array.
    
    var stringData = JSON.stringify(body);          // Change #2: stringify first.
    
    var postOptions = {
      host: 'localhost',
      port: '5984',
      path: '/members/_bulk_docs',
      method: 'POST',
      headers: {
          'Content-Type': 'application/json',
          'Content-Length': stringData.length       // Change #3: send the length of the stringified data.
      }
    };
    
    var request = http.request(postOptions, function(res){
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
          console.log('Response: ' + chunk);
        });
    });
    
    console.log(stringData);
    
    request.write(stringData);
    
    request.end();
    

    这是我从节点得到的输出:

    {"docs":[{"family":"Smith","people":{"Bob":{"name":"Bob","active":true,"birthday":"1/01"},"Sue":{"name":"Sue","active":true,"birthday":"1/01"}},"address":{"street":"1111 Cool Road","city":"Cincinnati","state":"OH","zip":"11111"},"phone":"923-4908"}]}
    
    Response: [{"ok":true,"id":"721b8cde7a1e22b4cc106adbb3f41df9","rev":"1-306b71ff83df48c588a174fd5feafa34"}]
    

    【讨论】:

    • 所以作为一个实验,我把节点生成的字符串写到一个文件中。然后我使用 curl 发布文件。那确实奏效了。这是一个很好的解决方法,所以我要赞成这个答案,但我希望有人能够告诉我节点中发生了什么。
    • 很高兴您发现这个答案很有用,并感谢您的支持。关于节点,你可以看看 coux(读作 couch)包:npmjs.org/package/coux
    • 您的代码已更改。请参阅我的答案中 UPDATE 标头后包含的节点代码。我所做的更改是 (1) 将结果包装在一个数组中,(2) 在生成发布选项之前对正文进行字符串化,以及 (3) 在发布选项中包括字符串化数据的长度。
    • doh,既然你指出了这一点,我 90% 的肯定是内容长度属性把事情搞砸了。我最初忘记对数据进行字符串化,然后一旦我修复了它,我就从未更正过内容长度。我今晚会测试,然后可能会接受你的答案。
    • 是的,抱歉,我这个周末有事,所以直到今晚才开始。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    • 1970-01-01
    相关资源
    最近更新 更多