【问题标题】:How to know what type to cast a JObject to when deserializing a JSON string反序列化 JSON 字符串时如何知道将 JObject 转换为什么类型
【发布时间】:2016-11-04 20:47:24
【问题描述】:

我知道过去有很多关于使用 Newtonsoft 进行反序列化的问题,但我一直无法找到与我的情况完全匹配的东西。 (如果我无意中问了一个重复的问题,请告诉我,我很难相信我是第一个遇到这种情况的人。

我有一个这样的对象结构:

public class Logger
    {
        public List<MethodAPI> List { get; set; }
    }

    private class MethodAPI
    {
        public string MethodName { get; set; }
        public List<Parameter> Parameters { get; set; }
    }

现在对于我在反序列化时遇到问题的类型。如果我执行以下操作:

    public class Parameter
    {
        public IProduct data { get; set; }
    }

然后反序列化就可以了。但是,直到运行时,我才真正知道 data 是什么类型。但是,如果我执行以下操作:

public class Parameter
{
   public object data { get; set; }
}

显然,当我去反序列化这个 Newtonsoft 时,它无法解决它实际上应该是什么类型。因此,它只是使其成为JObject

通常,我只会编写一个自定义转换器。但是,我不确定在这种情况下如何实现 ReadJson 方法。

public class ParameterConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType.Equals(typeof(Parameter));
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            // I'd rather just do serializer.Deserialize<Parameter>(reader) here but that'll cause a stack overflow exception
            object obj = serializer.Deserialize(reader);
            Parameter param = (obj as JObject).ToObject<Parameter>();

            // This works great if I know that I'm converting this to IProduct, but is there an elegant way to figure out what type to use here?
            // I have to pass the serializer here because the serializer can "map" IProduct and several of its "child" types to its implementation
            param.data = (param.data as JObject).ToObject(typeof(IProduct), serializer);
            return param;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            // Serialization's no problem
            serializer.Serialize(writer, value);
        }
    }

正如我在代码 cmets 中提到的,我感到困惑的部分是如何根据原始 JSON 确定原始对象的类型。有没有人对这样做的非可怕方式提出建议?

【问题讨论】:

  • 也许new JsonSerializerSettings() { TypeNameHandling = ......}
  • @L.B 谢谢,这似乎正是我所需要的——甚至不需要自定义转换器。
  • @L.B 如果您作为答案发布,我将很高兴接受/支持
  • EJoshuaS,您可以接受自己的答案。不需要重复同样的事情......

标签: c# json json.net deserialization


【解决方案1】:

感谢@L.B.在这个 - 我有点尴尬错过了这个,但我需要做的就是

new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Objects }

不需要自定义转换器。

我将暂时保留它,以防其他人发现它有用。

【讨论】:

    【解决方案2】:

    c# 中一个漂亮的新事物是新声明的类型dynamic。这与在 JavaScript 中声明 var 基本相同(如果您熟悉的话)。

    示例

    你的班级是:

    public class Parameter
    {
       public dynamic data { get; set; }
    }
    

    现在,我可以在代码中创建它的一个实例并按照我的意愿使用它:

    Parameter param = new Parameter();
    string foo = JsonConvert.SerializeObject(some_object);
    
    // If you know the object type (in this case the object type is IProduct)
    param.data = JsonConvert.DeserializeObject<IProduct>(foo);
    
    // If you don't know the object type
    param.data = JsonConvert.DeserializeObject<ExpandoObject>(foo, new ExpandoObjectConverter());
    

    expando 对象是一个 C# 类,它允许您创建动态对象,允许您调用任何方法并在运行时对其进行评估。

    例如

    dynamic foo = new ExpandoObject();
    // Creates a member variable named bar
    foo.bar = "Hello, World!";
    // Throws an runtime error because bar2 is undefined
    Console.WriteLine(foo.bar2);
    

    我不知道这是否是您的问题,但无论如何知道它会有所帮助:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-03
      相关资源
      最近更新 更多