简体   繁体   中英

Deserialize an Anonymous Type From a Collection

I have my serialized JSON in this format:

string json = @"[{"Name": "std_id","Value": "111"}, {"Name": "cust_id","Value": "444"}]"

How do I deserialize it to a single anonymous object like this:

var paramObj = new {"std_id" = 111, "cust_id" = 444}

Why anonymous object? you should deserialize to a type like below

public class RootObject
{
    public string Name { get; set; }
    public string Value { get; set; }
} 

Then what you actually have is IEnumerable<RootObjct> . You can use use Linq and select First() from it like

RootObject = RootObjects.FirstOrDefault()

You could deserialize it into a dynamic. Like this:

var serializer = new JavaScriptSerializer();
var deserializedResult = serializer.Deserialize<dynamic>(json);

Reference:

Since you said the values of the Name and Value properties in your JSON objects can vary, you will not be able to deserialize to an anonymous object. Anonymous types are defined at compile-time, which means you need to know the property names ahead of time to be able to define them. The only way to get around that is code generation, which I think is going to be overkill for this situation. Instead, I would suggest you deserialize into a JObject with a dynamic variable. This will get you pretty close to what you want. Here's how:

string json = @"[
  { ""Name"": ""std_id"", ""Value"": ""111"" },
  { ""Name"": ""cust_id"", ""Value"": ""444"" }
]";

dynamic obj = new JObject(JArray.Parse(json)
                  .Select(t => new JProperty((string)t["Name"], t["Value"])));

From there, you can access the properties like you would for an anonymous type (assuming you know what they are):

Console.WriteLine(obj.std_id);
Console.WriteLine(obj.cust_id);

If you don't know what the properties are, you can enumerate them like a dictionary:

foreach (var prop in obj)
{
    Console.WriteLine(prop.Name + ": " + prop.Value);
}

Fiddle: https://dotnetfiddle.net/MRY2ny

var definition = new { Name = "" };
string json1 = @"{'Name':'James'}";
var customer1 = JsonConvert.DeserializeAnonymousType(json1, definition);
Console.WriteLine(customer1.Name);
string json2 = @"{'Name':'Mike'}";
var customer2 = JsonConvert.DeserializeAnonymousType(json2, definition);
Console.WriteLine(customer2.Name);

source http://www.newtonsoft.com/json/help/html/DeserializeAnonymousType.htm

I know that this solution isn't perfect, but it works for the example provided by you and returns result that looks like paramObj in your example.

The idea is to create a custom Json converter.

First, let's create a DTO class to present a name-value item of incomming JSON.

public class NameValueJsonItem
{
    public string Name { get; set; }

    public string Value { get; set; }
}

Converter implementation:

public class DynamicJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override object ReadJson(JsonReader reader, Type objectType, 
        object existingValue, JsonSerializer serializer)
    {        
        JToken token = JToken.Load(reader);

        if (token == null || token.Type != JTokenType.Array)
        {
            return null;
        }

        List<NameValueJsonItem> parsedJson = token.ToObject<List<NameValueJsonItem>>();

        ExpandoObject result = new ExpandoObject();

        foreach (NameValueJsonItem item in parsedJson)
        {
            if (!String.IsNullOrEmpty(item.Name))
            {
                (result as IDictionary<string, object>)[item.Name] = item.Value;
            }
        }

        return result;
    }

    public override void WriteJson(JsonWriter writer, object value, 
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Sure, you can make it more safe by adding some exceptions handling etc inside the method if you want.

You can use this converter like that:

dynamic result = JsonConvert.DeserializeObject<dynamic>(json, new DynamicJsonConverter());

Hope it will help.

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