0

Does anyone have any suggestions on how to convert a json dictionary that has mixed single and array values into a C# concrete object. Dictionary int, dynamic does not work see json below.

{
    "outcome": "SUCCESS",
    "response": {
        "249998": "1203088",
        "249999": "1203091",
        "250000": "1203093",
        "250001": "1203095",
        "250003": "1203096",
        "250004": "1203102",
        "250005": "1203107",
        "250006": {
            "1203109": 1,
            "1203110": 0,
            "1203111": 0,
            "1203112": 0,
            "1203113": 0,
            "1203114": 0,
            "1203115": 0,
            "1203116": 0,
            "1203117": 0,
            "1203118": 0,
            "1203119": 0,
            "1203120": 0
        },
        "250007": {
            "1203121": 0,
            "1203122": 0,
            "1203123": 0,
            "1203124": 0,
            "1203125": 1,
            "1203126": 0,
            "1203127": 0,
            "1203128": 0
        },
        "250008": {
            "1203129": "fcdvgbjkl;"
        },
        "250010": "1203130",
        "250011": "1203135",
        "250012": "1203140",
        "250013": "1203145",
        "250014": "1203150",
        "250015": "1203155",
        "250017": "1203160",
        "250018": "1203165",
        "250019": "1203170",
        "250020": "1203175",
        "250021": "1203181",
        "250023": "1203183",
        "250024": "1203188",
        "250025": "1203193",
        "250026": "1203198",
        "250027": "1203203",
        "250028": "1203208",
        "250029": "1203213",
        "250030": "1203219",
        "250031": {
            "1203221": 0,
            "1203222": 0,
            "1203223": 0,
            "1203224": 0,
            "1203225": 1,
            "1203226": 0,
            "1203231": 0
        },
        "250036": {
            "1203236": 0,
            "1203237": 0,
            "1203238": 0,
            "1203243": 0,
            "1203244": 0,
            "1203245": 0,
            "1203246": 1,
            "1203247": 0,
            "1203248": 0,
            "1203249": 0,
            "1203250": 0,
            "1203251": 0,
            "1203252": 0,
            "1203253": 0,
            "1203254": 0,
            "1203255": 0,
            "1203256": 0,
            "1203257": 0,
            "1203258": 0,
            "1203259": 0
        },
        "250041": {
            "1203264": "gjhgjhg"
        },
        "250045": {
            "1203269": 0
        }
    }
}
Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
B_Manx
  • 27
  • 5
  • 1
    Possible duplicate of [How to Convert JSON object to Custom C# object?](http://stackoverflow.com/questions/2246694/how-to-convert-json-object-to-custom-c-sharp-object) – Jibin Balachandran Dec 05 '16 at 12:49
  • What is the error when you use dynamic type ? – PMerlet Dec 05 '16 at 12:51
  • Newtonsoft:Additional information: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Object[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. – B_Manx Dec 05 '16 at 13:00
  • Simple JSON gave an outside bounds of array error – B_Manx Dec 05 '16 at 13:01
  • Jibin not a duplicate question, Serializing Json to C Sharp objects is trivial. this particular issue is how to serialize Json created by people who probably shouldn't be allowed to program into a c sharp object. – B_Manx Dec 05 '16 at 13:05

2 Answers2

1

With the Newtonsoft.JSON package, you can do something like this:

public Dictionary<string, object> ParseJson(string json) {

    var obj = JObject.Parse(json);

    var dict = new Dictionary<string, object>();

    foreach (var property in obj) {
        var name = property.Key;
        var value = property.Value;

        if (value is JArray) {
            dict.Add(name, value.ToArray());
        }
        else if (value is JValue) {
            dict.Add(name, value.ToString());
        }
        else {
            throw new NotSupportedException("Invalid JSON token type.");
        }
    }

    return dict;    
}

In Newtonsoft, JObject is a class that represents any JSON object, JArray represents a JSON array, and JValue represents a scalar value.

In this method, we parse the incoming string as a JObject, this will also recursively parse any nested objects, arrays, and so on. Then we create an empty Dictionary<string, object> to use as our result. Then we loop through the top-level properties of our parsed JObject, and for each property, if the value is an array we add that to our dict, if its a scalar we add that, and if its something else like a nested object it throws a NotSupportedException. Finally the dictionary is returned.

In your case, there are a lot of integers, rather than strings, so you may need to sprinkle in some Int32.TryParse calls.

JamesFaix
  • 8,050
  • 9
  • 37
  • 73
  • Thank you. I tried jobject and Jarray as well. I think this JSON is just not good json. The Id's are being used more like property names than as keys – B_Manx Dec 05 '16 at 13:03
  • Ahh I see. So here you actually have nested `JObject`s, not a master `JObject` with child `JArrays`. You could just call `JObject.Parse` and just work with that `JObject` in memory, they're quite handy really. If you want to convert to standard collections though, you'll have to dig through the original object recursively in a way similar to what I posted. Is anything about the structure of your incoming JSON guaranteed? if so, you may want to create a few basic classes to represent the object graph. – JamesFaix Dec 05 '16 at 13:41
  • Ah I had forgotten about Jobject.Parse and was simply trying to deserialize into a jobject. That works. now to decide if I really want to write all the goofy logic needed to excavate the jobject. Thank you – B_Manx Dec 05 '16 at 13:56
0

You can use object as the value of a dictionary which will accept either strings or integers. You need a multiple level object like code below

public class MyClass
    {
        Dictionary<int, int> dict = new Dictionary<int, int>();
        Dictionary<int, object> childDict = new Dictionary<int, object>();
    }
jdweng
  • 33,250
  • 2
  • 15
  • 20