C# 如何使用 Newtonsoft.Json 将对象序列化为具有类型信息的 json?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19360133/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 14:50:04  来源:igfitidea点击:

How to serialize object to json with type info using Newtonsoft.Json?

c#serializationjson.net

提问by Exta

I want to have a property with type name in JSON when I serialize objects of certain types. I wrote a converter:

当我序列化某些类型的对象时,我想在 JSON 中有一个带有类型名称的属性。我写了一个转换器:

public class TypeInfoConverter : JsonConverter {
    private readonly IEnumerable<Type> _types;

    public TypeInfoConverter(IEnumerable<Type> types) {
        Contract.Requires(types != null);

        _types = types;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        var jObject = JObject.FromObject(value, serializer);
        jObject.AddFirst(new JProperty("Type", value.GetType().Name));
        jObject.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        return serializer.Deserialize(reader, objectType);
    }

    public override bool CanConvert(Type objectType) {
        return _types.Any(t => t.IsAssignableFrom(objectType));
    }
}

But when I'm trying to serialize object I have an infinity recursion here: var jObject = JObject.FromObject(value, serializer);It is obvious because I use the same instance of JsonSerializer which was configured with that converter.

但是当我尝试序列化对象时,我在这里有一个无限递归: var jObject = JObject.FromObject(value, serializer);很明显,因为我使用了与该转换器配置的 JsonSerializer 的相同实例。

How to prevent using this converter, but I want to use other converters which configured for this serializer?

如何防止使用此转换器,但我想使用为此串行器配置的其他转换器?

Types which I want to serialize:

我要序列化的类型:

public interface ITaskResult {
}

public class UserHasRejectedOffer : ITaskResult {
    public string Message { get; set; }
}

public class UserHasFilledForm : ITaskResult {
    public string FormValue1 { get; set; }

    public string Formvalue2 { get; set; }
}

...

采纳答案by Exta

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    var converters = serializer.Converters.Where(x => !(x is TypeInfoConverter)).ToArray();

    var jObject = JObject.FromObject(value);
    jObject.AddFirst(new JProperty("Type", value.GetType().Name));
    jObject.WriteTo(writer, converters);
}

回答by Brian Rogers

Have you tried creating a new instance of JsonSerializer, then copying all the converters from the original serializer except the converter that causes the infinite recursion?

您是否尝试过创建 的新实例JsonSerializer,然后从原始序列化程序中复制除导致无限递归的转换器之外的所有转换器?

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    JsonSerializerSettings settings = new JsonSerializerSettings
    {
        Converters = serializer.Converters.Where(s => !(s is TypeInfoConverter)).ToList()
        // also copy any other custom settings from the serializer you wish to pass through
        DateFormatHandling = serializer.DateFormatHandling,
        MissingMemberHandling = serializer.MissingMemberHandling,
        NullValueHandling = serializer.NullValueHandling,
        Formatting = serializer.Formatting
    };
    var localSerializer = JsonSerializer.Create(settings);

    var jObject = JObject.FromObject(value, localSerializer);
    jObject.AddFirst(new JProperty("Type", value.GetType().Name));
    jObject.WriteTo(writer);
}

回答by CalvinDale

var jsonSerializerSettings = new JsonSerializerSettings() { 
    TypeNameHandling = TypeNameHandling.All
};
var json = JsonConvert.SerializeObject(instance, jsonSerializerSettings);

http://james.newtonking.com/json/help/index.html?topic=html/SerializationSettings.htm

http://james.newtonking.com/json/help/index.html?topic=html/SerializationSettings.htm