Question

I'm trying to parse the following json: http://libris.kb.se/xsearch?query=%22design%22+language:%28%22ENG%22%29&format=json&format_level=full&database=swepub As you can see in the first item of the list element the description is a regular string. This is also true for the other 8 result but on the 9th result it, for some reason, turns into an array of strings instead.

I'm using C# and a DataContract trying to parse this but it will obviously not work as the type is different between the result. How can i work around this? I suppose to could just manually parse everything but I'd rather not do that.

This is my DataContract's

[DataContract]
public class SwepubHeader
{
    [DataMember(Name = "xsearch")]
    public SwepubBody Body { get; set; }
}

[DataContract]
public class SwepubBody
{
    [DataMember(Name = "from")]
    public int From { get; set; }

    [DataMember(Name = "to")]
    public int To { get; set; }

    [DataMember(Name = "records")]
    public int Records { get; set; }

    [DataMember(Name = "list")]
    public SwepubSearchItem[] SearchItems { get; set; }
}

[DataContract]
public class SwepubSearchItem
{
    [DataMember(Name = "isbn")]
    public string ISBN { get; set; }

    [DataMember(Name = "title")]
    public string Title { get; set; }

    [DataMember(Name = "description")]
    public string Description { get; set; }

    [DataMember(Name = "identifier")]
    public string Identifier { get; set; }

    [DataMember(Name = "type")]
    public string Type { get; set; }

    [DataMember(Name = "publisher")]
    public string Publisher { get; set; }

    [DataMember(Name = "date")]
    public string Date { get; set; }

    [DataMember(Name = "language")]
    public string Language { get; set; }

    [DataMember(Name = "relation")]
    public string Relation { get; set; }

    [DataMember(Name = "subject")]
    public string[] Subjects { get; set; }

    [DataMember(Name = "creator")]
    public string[] Creators { get; set; }
}

and this is how i parse it

                    using (var response = request.GetResponse() as HttpWebResponse)
                {
                    if (response != null)
                    {
                        if (response.StatusCode != HttpStatusCode.OK)
                            throw new Exception(String.Format(
                                "Server error (HTTP {0}: {1}).",
                                response.StatusCode,
                                response.StatusDescription));
                        var jsonSerializer = new DataContractJsonSerializer(typeof(SwepubHeader));
                        object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
                        var jsonResponse = objResponse as SwepubHeader;
                        return jsonResponse;
                    }
                }
Était-ce utile?

La solution

This really is not a great design for their JSON format, but you can handle it by having description being an object. Then, how you deal with that object is up to you, but you can create another property that converts it to what you need:

[DataMember(Name = "description"]
private object _description;

public string Description
{
    get
    {
        if (_description != null)
        {
            if (_description is string)
            {
                // Do Nothing
                // You can remove this, just putting this here to 
                //   show conditional is implicit
            }
            else if (_description is string[])
            {
                // Join string[] using '\n\n' as the connector
                _description = string.Join("\n\n", (string[])_description);
            }
        }

        return _description as string;
    }
}

Autres conseils

The url returns two different JSON objects. This really isn't a great design on their part but if you have no control over that then an option is to try to deserialize it with string data and if that fails deserialize it with an array of strings.

EDIT: In order to make this work easily you should have description deserialize to an object. However it isn't an array of strings... it's either a string or an array of objects... so the following code will handle this... replace your Description property with the following...

[DataMember(Name = "description")]
public object description { get; set; }

public string Description {
    get
    {
        var seperator = string.Empty; // replace with what you want
        var s = description as string;
        if (s != null)
            return s;
        var sArray = description as object[];
        if (sArray != null)
            return String.Join(seperator, sArray);
        return null;
    }
    set
    {
        description = value;
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top