0

I'm trying to parse an object response from a web API that I have no control

So, one of the responses is like this:

{
    "BatchID": 25,
    "Results": [{
        "ItemID": 123,
        "ResultMessage": "COMPLETED"
    }, {
        "ItemID": 456,
        "ResultMessage": "COMPLETED"
    }],
    "COMPLETED_COUNT": 2,
    "INPROGRESS_COUNT": 0,
    "FAILED_COUNT": 0
}

This is very easy to parse using NewtonSoft Json library; however I have encounter this as well:

{
    "3305": "COMPLETE",
    "7305": "COMPLETE",
    "COMPLETED_COUNT": 2,
    "INPROGRESS_COUNT": 0,
    "FAILED_COUNT": 0
}

I have no idea how many int properties I may encounter. In this example are only two "3305" and "7305"

My question is: is there a way I can create an object that can hold every integer in that response?

Thanks for your help.

5
  • 3
    Deserialize it as a Dictionary<string, object>, otherwise you probably need to deserialize one or two properties into a known structure, classify which specific structure the rest must have depending on these properties and then deserialize again when you know the type to deserialize into. Commented Nov 6, 2017 at 12:59
  • Also check this question which shows how to support both known properties as well as unknown properties without having everything in the "unknown" set. Commented Nov 6, 2017 at 13:03
  • Also be aware that while the keys here have digits in them, they are still strings. The fact that those strings contain numbers may be something you know to be true for all those extra properties but I would still handle them purely as strings. Commented Nov 6, 2017 at 13:04
  • Thanks I'll give this a try and let you know. Commented Nov 6, 2017 at 13:10
  • @LasseVågsætherKarlsenThanks for your tip. It worked very well. How can I mark your comment as solved? Commented Nov 7, 2017 at 15:16

2 Answers 2

1

You may want to try cast JSON acquired from API to the instance of JObject. It holds all properties with names & values

Sign up to request clarification or add additional context in comments.

Comments

0

To define a type that will deserialize the given json into a type that mimicks the known structure + some unknown structure, use Json.Net and use this type:

public class Response
{
    [JsonProperty("COMPLETED_COUNT")]
    public int CompletedCount { get; set; }

    [JsonProperty("INPROGRESS_COUNT")]
    public int InProgressCount { get; set; }

    [JsonProperty("FAILED_COUNT")]
    public int FailedCount { get; set; }

    [JsonExtensionData]
    public Dictionary<string, object> ExtraData { get; } = new Dictionary<string, object>();
}

Please know that the "Results" sub-property in the first json will be difficult to handle in this concept, so you should still strive to make a "detection" algorithm that looks at a subset of the properties, and if some specific key properties exists, pick a different and more correct type to deserialize the json into.

For instance, here is a simple such heuristics:

public static ResponseBase Classify(string json)
{
    var response = JsonConvert.DeserializeObject<ResponseBase>(json);

    if (response.ExtraData.ContainsKey("Results"))
        return JsonConvert.DeserializeObject<ResponseWithResults>(json);

    return response;
}

public class ResponseBase
{
    [JsonProperty("COMPLETED_COUNT")]
    public int CompletedCount { get; set; }

    [JsonProperty("INPROGRESS_COUNT")]
    public int InProgressCount { get; set; }

    [JsonProperty("FAILED_COUNT")]
    public int FailedCount { get; set; }

    [JsonExtensionData]
    public Dictionary<string, object> ExtraData { get; } = new Dictionary<string, object>();
}

public class ResponseWithResults : ResponseBase
{
    public int BatchId { get; set; }
    public List<ResponseResult> Results { get; } = new List<ResponseResult>();
}

public class ResponseResult
{
    public int ItemId { get; set; }
    public string ResultMessage { get; set; }
}

Do note that this deserializes the json twice. There are different ways to handle/avoid that but you will have to decide if this is a valid way forward.

1 Comment

That was what I was looking for.

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.