简体   繁体   中英

C#: How to parse JSON enums

I have a JSON string I want to convert into one of many possible types depending on type :

{
"type": "x",
"val": {...}
}

type is an enum. val should only match a type associated with that particular enum key. All possible valid val 's will have corresponding C# classes.

Is it possible to do this in one pass (instead of first parsing type only, and then using a switch to try and parse val into the correct type).

How would this be done recursively without having to hand write code to map the valid type/val combinations? Eg if this "JSON enum" pattern was nested so the val object contains another type .

Thanks

Have you tried this one? I use Newtonsoft.Json and it works. I use "X" and "Y" strings and it parse them by custom converter.

Use Polymorphism to map the dynamic values.

Check the sample code:

public enum MyType
{
    X,
    Y
}

public class MyJsonWithType
{
    public MyType Type { get; set; }
    public IValueHeader Val { get; set; }
}

public interface IValueHeader
{

}

public class MyJsonDetail1 : IValueHeader
{
    public string SomeStr { get; set; }
}

public class MyJsonDetail2 : IValueHeader
{
    public int SomeInt { get; set; }
}

public class MyTypeConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(MyJsonWithType).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartObject)
        {
            JObject item = JObject.Load(reader);
            if (item["Type"] != null)
            {
                var myType = item["Type"].ToObject<MyType>(serializer);
                if (myType == MyType.X)
                {
                    var xObject = item["Val"].ToObject<MyJsonDetail1>(serializer);
                    return new MyJsonWithType
                    {
                        Type = myType,
                        Val = xObject
                    };
                }
                else if (myType == MyType.Y)
                {
                    var yObject = item["Val"].ToObject<MyJsonDetail2>(serializer);
                    return new MyJsonWithType
                    {
                        Type = myType,
                        Val = yObject
                    };
                }
            }
        }

        return null;
    }

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

static void Main(string[] args)
{
    string newJson1 = "{\"Type\":\"X\",\"Val\":{\"SomeStr\":\"Test\"}}";
MyJsonWithType newTypeX = JsonConvert.DeserializeObject<MyJsonWithType>(newJson1, new MyTypeConverter());

    string newJson2 = "{\"Type\":\"Y\",\"Val\":{\"SomeInt\":5566}}";
MyJsonWithType newTypeY = JsonConvert.DeserializeObject<MyJsonWithType>(newJson2, new MyTypeConverter());


    DisplayMyTypeValue(newTypeX.Val);
    DisplayMyTypeValue(newTypeY.Val);
}

private static void DisplayMyTypeValue(IValueHeader val)
{
    if (val is MyJsonDetail1)
    {
        Console.WriteLine((val as MyJsonDetail1).SomeStr);
    }
    else if (val is MyJsonDetail2)
    {
        Console.WriteLine((val as MyJsonDetail2).SomeInt);
    }
}

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