如何将复杂的JSON值映射到简单对象的数组

时间:2017-11-07 18:02:03

标签: javascript json typescript

我有以下JSON,它由webservice返回:

[{
    "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 IListItem

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

3 个答案:

答案 0 :(得分:2)

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

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;    

答案 1 :(得分: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)));

答案 2 :(得分:-1)

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

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

编辑:

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