简体   繁体   English

C#:如何解析 JSON 枚举

[英]C#: How to parse JSON enums

I have a JSON string I want to convert into one of many possible types depending on type :我有一个 JSON 字符串我想根据type转换为许多可能的类型之一:

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

type is an enum. type是一个枚举。 val should only match a type associated with that particular enum key. val应该只匹配与该特定枚举键关联的类型。 All possible valid val 's will have corresponding C# classes.所有可能的有效val都将具有相应的 C# 类。

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).是否可以一次完成(而不是仅首先解析type ,然后使用switch尝试将val解析为正确的类型)。

How would this be done recursively without having to hand write code to map the valid type/val combinations?这将如何以递归方式完成,而无需将有效的类型/值组合手写代码到 map? Eg if this "JSON enum" pattern was nested so the val object contains another type .例如,如果这个“JSON 枚举”模式是嵌套的,那么val object 包含另一种type

Thanks谢谢

Have you tried this one?你试过这个吗? I use Newtonsoft.Json and it works.我使用Newtonsoft.Json并且它有效。 I use "X" and "Y" strings and it parse them by custom converter.我使用“X”和“Y”字符串并通过自定义转换器解析它们。

Use Polymorphism to map the dynamic values.使用多态性对 map 的动态值。

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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