如何获取 JObject.FromObject(object) 以包含类型信息



假设我有以下内容(我的实际代码的非常简化的版本;假设WrapperC有更多未显示的成员(:

interface I { }
class C : I
{
    public string Name { get; set; }
}
class Wrapper
{
    public I Instance { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        Wrapper wrapper = new Wrapper
        {
            Instance = new C { Name = "Test" }
        };
        JsonSerializerSettings settings = new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.Auto
        };
        Console.WriteLine(JsonConvert.SerializeObject(wrapper, Formatting.Indented, settings));
    }
}

输出将包括 Instance 的类型信息,因为实际类型与其声明的类型不同,正如预期的那样:

{
  "Instance": {
    "$type": "ConsoleApplication.C, ConsoleApplication",
    "Name": "Test"
  }
}

相反,假设我使用自定义JsonConverterWrapper

class WrapperConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Wrapper);
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Wrapper wrapper = (Wrapper)value;
        JObject root = new JObject();
        JObject instance = JObject.FromObject(wrapper.Instance);
        root.Add("Instance", instance);
        root.WriteTo(writer);
    }
}

这不再输出实例的类型信息:

{
  "Instance": {
    "Name": "Test"
  }
}

WrapperConverter.WriteJson中手动构造JObject时,如何强制包含Instance的类型信息?

为了发出"$type" TypeNameHandling.Auto根对象的信息,您需要使用具有预期根类型参数的JsonSerializer.Serialize()重载之一:

  • JsonSerializer.Serialize(JsonWriter, Object, Type)
  • JsonSerializer.Serialize(TextWriter, Object, Type)

但是,正如您已经注意到的,没有允许传递预期根类型的JObject.FromObject()重载。 因此,您将使用JTokenWriter手动构建JObject

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Wrapper wrapper = (Wrapper)value;
        JObject root = new JObject();
        using (var tokenWriter = new JTokenWriter())
        {
            serializer.Serialize(tokenWriter, wrapper.Instance, typeof(object));
            root.Add("Instance", tokenWriter.Token);                
        }
        root.WriteTo(writer);
    }

您还可以通过跳过中间JObject表示形式来提高性能:

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Wrapper wrapper = (Wrapper)value;
        writer.WriteStartObject();
        writer.WritePropertyName("Instance");
        serializer.Serialize(writer, wrapper.Instance, typeof(object));
        writer.WriteEndObject();
    }

如果将WriteJson修改为:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    var wrapper = (Wrapper)value;
    var root = new JObject();
    var instance = JObject.FromObject(wrapper.Instance, new JsonSerializer
    {
        TypeNameHandling = TypeNameHandling.Objects
    });
    root.Add("Instance", instance);
    root.WriteTo(writer);
}

它还将输出 $type 属性。

相关内容

  • 没有找到相关文章

最新更新