【问题标题】:How to map a complex JSON value to an array of simple objects如何将复杂的 JSON 值映射到简单对象的数组
【发布时间】:2017-11-07 18:02:03
【问题描述】:

我有以下由网络服务返回的 JSON:

[{
    "Author": {
      "Title": "Luis Valencia"
    },
    "Editor": {
      "Title": "Luis Valencia"
    },
    "Id": 1,
    "ID": 1,
    "Title": "Generic List Item 1",
    "Modified": "2017-10-23T20:02:22Z",
    "Created": "2017-10-23T20:02:22Z"
  },
  {
    "Author": {
      "Title": "Luis Valencia"
    },
    "Editor": {
      "Title": "Luis Valencia"
    },
    "Id": 2,
    "ID": 2,
    "Title": "Generic List Item 2",
    "Modified": "2017-11-07T17:52:34Z",
    "Created": "2017-11-07T17:52:34Z"
  }
]

使用此代码:

let items: IListItem[];
    // tslint:disable-next-line:max-line-length
requester.get(
    `${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Modified,Created,Author/Title,Editor/Title&$expand=Author,Editor`,
    SPHttpClient.configurations.v1,
    {
        headers: {
            "Accept": "application/json;odata=nometadata",
            "odata-version": ""
        }
    }
)
.then((response: SPHttpClientResponse): Promise<{ value: IListItem[] }> => {
    return response.json() 
})
.then((json: { value: IListItem[] }) => {
    console.log(JSON.stringify(json.value));
    return this._listItems = json.value;
  });
break;    

如何将 json.value 转换为 IListItem 数组?这将在 THEN 语句中完成,但不知道如何。

更新 1 列表项

export  interface IListItem {
    [key: string]: any;
    id: string;
    title: string;
    modified: Date;
    created: Date;
    modifiedby: string;
    createdby: string;
}

【问题讨论】:

    标签: javascript json typescript


    【解决方案1】:

    尝试将您在 json 中收到的数组映射到 .then 方法中的新数组 IListItem,如下所示。

    let items: IListItem[];
        // tslint:disable-next-line:max-line-length
    requester.get(
        `${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id,Modified,Created,Author/Title,Editor/Title&$expand=Author,Editor`,
        SPHttpClient.configurations.v1,
        {
            headers: {
                "Accept": "application/json;odata=nometadata",
                "odata-version": ""
            }
        }
    )
    .then((response: SPHttpClientResponse): Promise<{ value: [] }> => {
        return response.json() 
    })
    .then((json: { value: [] }) => {
        console.log(JSON.stringify(json.value));
        this.items=json.value.map((v,i)=>({ 
            key: v.id,
            id: v.id,
            title: v.Title,
            createdBy: v.Author.Title,
            ..... //other fields go here.
        })
    
      });
    break;    
    

    【讨论】:

      【解决方案2】:

      有点晚了,但这里有一个类似的答案:

      .then(json => {
          const items = [];
          for (const obj of json) {
              const listItem: IListItem = {
                  id: String(obj.ID),
                  title: obj.Title,
                  modified: obj.Modified,
                  created: obj.Created,
                  modifiedby: obj.Editor.Title,
                  createdby: obj.Author.Title
              }
              items.push(listItem);
          }
          return this._listItems = items;
      })
      

      另见this fiddle


      作为旁注,您可以使用两个接口,一个用于您从 Web 服务接收的 JSON 对象,一个用于您在 API 中使用的对象。像这样的:

      interface IListSubItemJSON {
          title: string;
      }
      
      interface IListItemJSON {
          Author: IListSubItem;
          Editor: IListSubItem;
          ID: number;
          Title: string;
          Modified: Date;
          Created: Date;
      }
      
      interface IListItem {
          [key: string]: any;
          id: string;
          title: string;
          modified: Date;
          created: Date;
          modifiedby: string;
          createdby: string;
      }
      
      class ListItem implements IListItem {
          id: string;
          title: string;
          modified: Date;
          created: Date;
          modifiedby: string;
          createdby: string;
      
          private constructor(id ? : string, title ? : string, created ? : Date, modified ? : Date, createdby ? : string, modifiedby ? : string) {
              this.id = id;
              this.plantName = plantName;
              this.version = version;
          }
      
          public static createFromJSON(json: IListItemJSON): ListItem {
              return new ListItem(json.plantCode, json.plantName, json.version);
          }
      
          public static createFromJSONArray(json: IListItemJSON[]): ListItem[] {
              const items: ListItem[] = [];
              for (const item of json) {
                  const listItem: ListItem = ListItem.createFromJSON(item);
                  items.push(listItem);
              }
              return items;
          }
      
          public toJSON(): ListItemJSON {
              ...
              return new ListItemJSON(...);
          }
          ...
      }
      

      通过这种方式,您不再强烈依赖 Web 服务数据结构,因为如果它们修改,您只需调整映射。

      您的“then”代码简化为:

      .then(((json: {
          value: IListItemJSON[]
      }):ListItem[]) => (this._listItems = ListItem.createFromJSONArray(json.value)));
      

      【讨论】:

        【解决方案3】:

        看起来您希望在响应中返回 JSON(即将 Accept 标头设置为 application/json),但实际上您正在返回 XML。我通常不会期望 request.json() 尝试将 XML 强制转换为纯 javascript 对象。

        您需要在response.json() 之外实现一些额外的逻辑来解析您的回复。

        编辑:

        假设您的服务器无法配置为实际返回 JSON,您可能需要引入 XML 解析库。请记住,XML 不能直接映射到 JSON;它们根本不同。这意味着您可能需要做一些额外的工作,而不仅仅是将文档传递给某个库函数。如果没有更具体的问题,我能做的就是向您指出一些资源:

        【讨论】:

        • 这正是我的问题
        • 哦。我懂了。您的意思是第一个 .then 块。我会编辑。
        • 请看Update1,这样你能给出更准确的答案吗?
        • 我更改了问题的标题以更好地反映手头的问题
        猜你喜欢
        • 2018-07-28
        • 1970-01-01
        • 2018-03-10
        • 2020-03-08
        • 2019-02-06
        • 2018-10-27
        • 1970-01-01
        • 2016-06-14
        • 2019-08-25
        相关资源
        最近更新 更多