如何定义一个c#类来表示可以在其实现中变化的json对象

时间:2017-10-03 23:59:13

标签: c# json json.net

我正在为Minecraft实体定义编写解析器。我在数据中找到了这种惯例,其中像“roll”这样的对象可以这样定义

"rolls": {
    "min": 2,
    "max": 2
 }

但也可以这样定义

  "rolls": 1

我正在使用Newtonsoft JSON.net,以防有人知道json.net的方式来做到这一点。我只是不确定是否有一种简单的方法用c#

来表示这种变化

2 个答案:

答案 0 :(得分:2)

为此,我使用了c#type dynamic。它使您能够从对象中读取变量,就像它是强类型一样。

在你的情况下..

dynamic myObj = //your JSON deserialize method

//first example (Take note of the array)
int min = myObj.rolls[0].min;
int max = myObj.rolls[0].max;

//your second example
int numRolls = myObj.rolls;

请注意,您将不会获得任何代码建议,但它确实在运行时工作,只要正确反序列化JSON即可。如果在dynamic myObj行上放置断点,它可以提供帮助,因此您可以准确地看到对象的组成部分。

我不确定它的内存使用/安全可用性,也许有人可以发表评论?

注意 :这是用于一个不断变化且不受我控制的数据结构中,几十个类已经有几十个创造和维护。可能还有更好的方法,但如果您的示例是您将面临的最复杂的结构,那么您最好只创建这两个类并反序列化为正确的结构。

答案 1 :(得分:0)

这需要花费很长时间才能完成,这个解决方案可能不是最优的,但是这段代码确实有用

        class RollsConverter : JsonConverter
        {
            public override bool CanConvert(Type objectType)
            {
                return (objectType == typeof(Rolls));
            }

            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                JToken token = JToken.Load(reader);
                if (token.Type == JTokenType.Object)
                {
                    return token.ToObject<Rolls>();
                }

                return new Rolls(token.ToObject<Int64>());
            }

            public override bool CanWrite
            {
                get { return true; }
            }

            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                JToken t = JToken.FromObject(value);
                Rolls rolls = value as Rolls;

                if (rolls.Value > 0)
                {
                    writer.WriteValue(rolls.Value);
                }
                else
                {
                    JObject o = (JObject)t;

                    o.WriteTo(writer);
                }
            }
        }


        public class Rolls 
        {
            public Rolls(Int64 val)
            {
                Value = val;
            }

            public static implicit operator Rolls(Int64 value)
            {
                return new Rolls(value);
            }

            public bool ShouldSerializeMin()
            {
                // Only is value is unspecified
                return Value == 0;
            }

            public bool ShouldSerializeMax()
            {
                // Only is value is unspecified
                return Value == 0;
            }


            public bool ShouldSerializeValue()
            {
                // Only is value is specified
                return Value > 0;
            }

            [JsonProperty(PropertyName = "min", NullValueHandling = NullValueHandling.Ignore)]
            public Int64 Min { get; set; }

            [JsonProperty(PropertyName = "max", NullValueHandling = NullValueHandling.Ignore)]
            public Int64 Max { get; set; }

            [JsonIgnore]
            public Int64 Value { get; set; }
        }


        [JsonProperty(PropertyName = "rolls", NullValueHandling = NullValueHandling.Ignore)]
        [JsonConverter(typeof(RollsConverter))]
        public Rolls Roll { get; set; }