1

I have the following JSON which is returned by a 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"
  }
]

Using this code:

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;    

How can convert the json.value to an Array of IListItem? that would be done in the THEN statement, but dont know how to.

Update 1 IListItem

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

3 Answers 3

3
+50

Try mapping the array you receive in your json to a new array of IListItem in the .then method as follows.

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;    
Sign up to request clarification or add additional context in comments.

Comments

2

A bit late but here's a similar answer:

.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;
})

see this fiddle also.


As a side note you could use two interfaces, one for the JSON objects you receive from your webservice and one for the objects you use in your API. Something like this:

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(...);
    }
    ...
}

This way you no longer have a strong dependency on the webservice data structures in the sense that if they modify you only need to adapt your mappings.

Your 'then' code simplifies to:

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

Comments

-1

It looks like you are expecting to get JSON back in the response, (i.e. setting the Accept header to application/json), but you are actually getting back XML. I wouldn't normally expect request.json() to attempt to coerce the XML to a plain javascript object.

You will need to implement some additional logic beyond response.json() to parse your response.

EDIT:

Assuming your sever can't be configured to actually return JSON, you will likely want to pull in an XML parsing library. Keep in mind XML cannot map directly to JSON; they are fundamentally different. This means you likely have to do some additional work than just passing your document to some library function. Without a more specific question the best I can do is point you to some resources:

4 Comments

that is exactly my question
Oh. I see. You meant the first .then block. I'll edit.
please see Update1, with this can you give a more precise answer?
I changed the title of the question to better ressemble the problem at hand

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.