简体   繁体   中英

Convert complex JSON to Generic List using Newtonsoft

Below is a Json :

[{
    "Result": {
        "description": "Application Security Supp Specialist",
        "code": "40000003"
    }
}, {
    "Result": {
        "description": "Gvt Cyber Intelligence Specialist",
        "code": "40001416"
    }
}, {
    "Result": {
        "description": "Gvt Record Retention Specialist",
        "code": "40001428"
    }
}]

And below is the class structure which i have created as i need to fill this into a C# object. I am trying to create a collection of RulesEngineOutput and fill it with the json contents.

public class RulesEngineOutput
{
    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("code")]
    public string Code { get; set; }
}

public class RulesEngineOutputCollection
{
    public IEnumerable<RulesEngineOutput> ProbableRoles { get; set; }
}

I am trying to achieve this using below code :

var bodyJson = JsonConvert.SerializeObject(bodyString);
RulesEngineOutputCollection result = new RulesEngineOutputCollection();
foreach (var item in bodyJson)
{
    result = JsonConvert.DeserializeObject<RulesEngineOutputCollection>(item.ToString()); 
}

But this is throwing exception as the item gets a char, what i am thinkiong is that i need to pass a JSON object in the loop but i am not able to get one. Everytime i get is a JSON string.

Cannot deserialize the current JSON array (eg [1,2,3]) into type 'RulesEngineOutputCollection' because the type requires a JSON object (eg {\\"name\\":\\"value\\"}) to deserialize correctly.\\r\\nTo fix this error either change the JSON to a JSON object (eg {\\"name\\":\\"value\\"}) or change the deserialized type to an array or a type that implements a collection interface (eg ICollection, IList) like List that can be deserialized from a JSON array.

The problem is that you have an intermediary object between your RulesEngineOutput and your collection. You need to restructure your objects as such:

public class RulesEngineOutput
{
    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("code")]
    public string Code { get; set; }
}

public class RulesEngineOutputResult
{
    public RulesEngineOutput Result { get; set; }
}

public class RulesEngineOutputCollection
{
    public IEnumerable<RulesEngineOutputResult> ProbableRoles { get; set; }
}

And then when you have this restructuring done, you can deserialize directly to your RulesEngineOutputCollection instead of to an object and iterating and deserializing again.

result = JsonConvert.DeserializeObject<RulesEngineOutputCollection>(bodyString); 

Thanks a lot Max,Nathan and others. So finally i made some changes in code and below is the code which i changed tomake the things work :

 var jToken = JObject.Parse(responseContent);
        var bodyString = jToken.SelectToken("body");
        var bodyJson = JsonConvert.SerializeObject(bodyString);


        List<RulesEngineOutput> result = new List<RulesEngineOutput>();


        try
        {

            foreach (var item in bodyString)
            {
                var formattedItem = item.SelectToken("Result");
                var  resultItem = JsonConvert.DeserializeObject<RulesEngineOutput>(formattedItem.ToString());
                   result.Add(resultItem);
            }


        }

Hope it helps others as well.

As Nathan Werry said, you have an object layered into another object and because of that, you cannot deserialize the data in the way you want it. However, you can work around that if you first create an array of these results and assign it later to your ProbableRoles property:

var rules = new RulesEngineOutputCollection
{
    ProbableRoles = JsonConvert.DeserializeObject<Result[]>(bodyString).Select(r => r.Data).ToList()
};

public class Result
{
    [JsonProperty("Result")]
    public RulesEngineOutput Data { get; set; }
}

Everything else stays the same. You basically create a new list out of your array of results. I could also assign the Select() result directly (without calling .ToList() ) but this ensures that the object actually has the data and not just a reference to an enumeration.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM