【问题标题】:Turn Observable Array into nested JSON将 Observable Array 转为嵌套 JSON
【发布时间】:2015-10-11 12:09:34
【问题描述】:

我在获取正确存储为 JSON 的信息数组时遇到问题。

我做了一个fiddle to illustrate the problem。输入一组标签并查看控制台以查看输出。

更多解释:

所以我有一个输入以逗号分隔的标签列表,然后我对其进行格式化。

function createTagArray() {
   // given an input value of 'tag1, tag2, tag3'
   // returns array = ['tag1', 'tag2', 'tag3']
} 

我认为接下来我需要做的是: 遍历数组并为每个项目创建一个“标签”对象,该对象还包括标签的 id 和标签关联的联系人的 id。

每个对象都被推送到tags,一个可观察的数组。

function single_tag(id, contactId, tagLabel) {
    var self = this;

    self.id = id;
    self.contactId = contactId;
    self.tagLabel = tagLabel;
}

function createTags() {
  var array = createTagArray();

  for (var i = 0; i < array.length; i++) {
    self.tags().push(new single_tag(uuid.generate(), self.contactId, array[i]));
  }
}

然后,我将其转换为 JSON

self.contactInformation = function() {
  return ko.toJS({
    "id": self.contactId,
    "firstname": self.firstname(),
    "lastname": self.lastname(),
    ... other fields ...
    "tags": self.tags(),
  })
}

但是,当我检查调用此函数的控制台输出时,标签是数组的集合,而不是一个好的 json 对象。

如何正确格式化?

我试过this suggestion,标签json的结构是正确的,但它是用转义引号存储的,所以看起来不对。

感谢大家的帮助!

【问题讨论】:

  • 仅供参考,您的示例已损坏。表单绑定中有错字。 sumbit =&gt; submit
  • 谢谢!这就解释了为什么它试图发布表单。

标签: javascript jquery arrays json knockout.js


【解决方案1】:

我会推荐你​​ KO 的 knockout.mapping 插件,它允许将复杂的 JSON 结构映射到视图模型,即使没有声明。

来自documentation

假设您有一个如下所示的 JavaScript 对象:

var data = {
    name: 'Scot',
    children: [
        { id : 1, name : 'Alicw' }
    ]
}

您可以毫无问题地将其映射到视图模型:

var viewModel = ko.mapping.fromJS(data);

现在,假设数据已更新为没有任何拼写错误:

var data = {
    name: 'Scott',
    children: [
        { id : 1, name : 'Alice' }
    ]
}

这里发生了两件事:名称从 Scot 更改为 Scott 并且 children[0].name 更改Alicw 致无错字的Alice。您可以根据这些新数据更新 viewModel:

ko.mapping.fromJS(data, viewModel);

并且名称会按预期更改。但是,在 children 数组中,孩子 (Alicw) 将被完全删除并添加一个新的 (Alice)。这并不完全是您所期望的。相反,您会期望只有孩子的 name 属性从 Alicw 更新到 Alice,而不是替换整个孩子!

...

要解决此问题,您可以指定映射插件应使用哪个键来确定对象是新对象还是旧对象。你可以这样设置:

var mapping = {
    'children': {
        key: function(data) {
            return ko.utils.unwrapObservable(data.id);
        }
    }
}
var viewModel = ko.mapping.fromJS(data, mapping);

【讨论】:

    【解决方案2】:

    在 jsfiddle 中,您使用的是不支持 textInput 的 Knockout 3.0。这是在 3.2 中添加的。要使用 3.2 版,您需要使用如下 cdn:http://cdnjs.com/libraries/knockout

    您的绑定中有 typeo。 sumbit 应该是 submit

    single_tag 的构造函数存在问题。 id 没有被使用,所以我删除了它:

    function single_tag(contactId, tagLabel) {
        var self = this;
    
        self.contactId = contactId;
        self.tagLabel = tagLabel;
    }
    

    目前也没有设置 contactId,因为 observable 尚未设置为值。

    要转换为 JSON,您需要使用 ko.toJSON 而不是 ko.toJS

    self.contactInformation = function() {
        return ko.toJSON({
          "firstname": self.firstname(),
          "tags": self.tags(),
        })
    }
    

    现在当控制台写出一个数组时:

    {
      "firstname":"test",
      "tags":[
        {"tagLabel":"test1"},
        {"tagLabel":"test2"},
        {"tagLabel":"test3"}
      ]
    }
    

    JsFiddle

    【讨论】:

    • 感谢您的浏览。我确实尝试过使用 toJSON,但这在我的 JSON 数据库中存储为转义字符串。 toJS 存储正确,但显然存在标签问题。顺便说一句,淘汰赛版本非常受欢迎!
    【解决方案3】:

    所以我的问题比我意识到的更基本。我正在使用 JSON 服务器来提供我的数据,并且我从数据库的两个部分(联系人和标签)中提取信息。

    当我尝试更新我的标签时,我试图将它们应用于我的数据库中联系人 JSON 中不存在的属性。但是单独发布标签是可行的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-16
      • 2014-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-01
      • 2017-11-22
      相关资源
      最近更新 更多