在反序列化JSON字符串时,如何知道将JObject转换为什么类型

时间:2016-11-04 20:47:25

标签: c# json json.net deserialization

我知道过去使用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; }
}

显然,当我去反序列化时,这个牛顿软件无法解决实际上应该采用的类型。因此,它只是使它成为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);
        }
    }

正如我在代码注释中提到的,我感到困惑的部分是如何确定原始对象基于原始JSON的类型。有没有人对这种非丑陋的方式提出建议?

2 个答案:

答案 0 :(得分:1)

感谢@ L.B.在这一个 - 我有点不好意思错过了这个,但我需要做的只是

false

无需自定义转换器。

如果其他人觉得它有用,我现在就把它留下来。

答案 1 :(得分:0)

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

我不知道这是不是你的问题,但无论如何都要知道:)