简体   繁体   English

将可观察数组转换为嵌套JSON

[英]Turn Observable Array into nested JSON

I'm having a problem getting an array of information stored properly as JSON. 我在将一系列信息正确存储为JSON时遇到问题。

I made a fiddle to illustrate the problem . 摆弄一个小提琴来说明这个问题 Enter a set of tags and take a look at the console to see the output. 输入一组标签并查看控制台以查看输出。

More explanation: 更多说明:

So I have an input that takes in a comma-separated list of tags, which I then format. 因此,我有一个输入,其中包含以逗号分隔的标记列表,然后将其格式化。

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

I thought what I needed to do next was the following: loop over the array and create a 'tag' object for each item which also includes an id for the tag and the id of the contact the tag is associated with. 我认为接下来需要做的是:在数组上循环并为每个项目创建一个“标签”对象,其中还包括标签的ID和与标签关联的联系人的ID。

Each object is pushed to tags , an observable array. 每个对象都被推到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]));
  }
}

Then, I converted it into JSON 然后,我将其转换为JSON

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

But, when I inspect the console output of calling this function, tags is a collection of arrays, not a nice json object. 但是,当我检查调用此函数的控制台输出时,标签是数组的集合,而不是漂亮的json对象。

混乱标签JSON

How do I get it formatted correctly? 如何正确格式化?

I tried this suggestion , and the tag json is structured correctly, but it is stored with escaped quotes, so that seems wrong. 我尝试了此建议 ,并且标签json的结构正确,但它与转义引号一起存储,因此这似乎是错误的。

Thanks for all the help! 感谢您的所有帮助!

I would recommend you knockout.mapping plugin for KO, it allow map complicated JSON structure to view model, even without declarations. 我建议您为KO使用基因敲除插件(knockout.mapping),它允许映射复杂的JSON结构来查看模型,即使没有声明也是如此。

From the documentation 文档中

Let's say you have a JavaScript object that looks like this: 假设您有一个如下所示的JavaScript对象:

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

You can map this to a view model without any problems: 您可以将其映射到视图模型,而不会出现任何问题:

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

Now, let's say the data is updated to be without any typos: 现在,假设数据已更新为没有任何错字:

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

Two things have happened here: name was changed from Scot to Scott and children[0].name was changed from Alicw to the typo-free Alice . 这里发生了两件事:名称从Scot更改为Scottchildren [0] .nameAlicw更改为错字的Alice You can update viewModel based on this new data: 您可以根据以下新数据更新viewModel:

ko.mapping.fromJS(data, viewModel);

And name would have changed as expected. 而且名称将按预期更改。 However, in the children array, the child (Alicw) would have been completely removed and a new one (Alice) added. 但是,在children数组中,子级(Alicw)将被完全删除,并添加一个新的子级(Alice)。 This is not completely what you would have expected. 这并不完全是您所期望的。 Instead, you would have expected that only the name property of the child was updated from Alicw to Alice, not that the entire child was replaced! 相反,您可能希望仅将子项的name属性从Alicw更新为Alice,而不是替换整个子项!

... ...

To solve this, you can specify which key the mapping plugin should use to determine if an object is new or old. 要解决此问题,您可以指定映射插件应使用哪个键来确定对象是新对象还是旧对象。 You would set it up like this: 您可以这样设置:

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

In the jsfiddle you were using Knockout 3.0 which doesn't have support for textInput. 在jsfiddle中,您使用的是Knockout 3.0,它不支持textInput。 This was added in 3.2. 这是在3.2中添加的。 To use version 3.2 you need to use a cdn such as this: http://cdnjs.com/libraries/knockout 要使用3.2版,您需要使用以下CDN: http ://cdnjs.com/libraries/knockout

There was typeo in your binding. 您的装订中有打字错误。 sumbit should be submit . 应该submit sumbit

There was a problem with your constructor for single_tag . 您的single_tag构造函数存在问题。 id was not used so I removed it: id未使用,因此我将其删除:

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

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

Currently also contactId is not set because the observable has not been set to a value. 当前也未设置contactId,因为尚未将observable设置为值。

To convert to JSON you need to use ko.toJSON instead of ko.toJS : 要转换为JSON,您需要使用ko.toJSON而不是ko.toJS

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

Now when the console writes out an array appears: 现在,当控制台写出一个数组时:

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

JsFiddle JsFiddle

So my problem was more basic than I was realizing. 所以我的问题比我意识到的更基本。 I'm using JSON Server to serve up my data, and I was pulling information from two parts of the database (contacts & tags). 我正在使用JSON Server提供数据,并且正在从数据库的两个部分(联系人和标签)中提取信息。

When I tried to update my tags, I was trying to apply them to a property that didn't exist on the contact JSON in my database. 当我尝试更新标签时,我试图将其应用于数据库中的联系人JSON上不存在的属性。 Posting the tags separately worked though. 不过,分别发布标签是可行的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM