1. <tfoot id='kzGIX'></tfoot>
        <bdo id='kzGIX'></bdo><ul id='kzGIX'></ul>
        <legend id='kzGIX'><style id='kzGIX'><dir id='kzGIX'><q id='kzGIX'></q></dir></style></legend>

        <small id='kzGIX'></small><noframes id='kzGIX'>

      1. <i id='kzGIX'><tr id='kzGIX'><dt id='kzGIX'><q id='kzGIX'><span id='kzGIX'><b id='kzGIX'><form id='kzGIX'><ins id='kzGIX'></ins><ul id='kzGIX'></ul><sub id='kzGIX'></sub></form><legend id='kzGIX'></legend><bdo id='kzGIX'><pre id='kzGIX'><center id='kzGIX'></center></pre></bdo></b><th id='kzGIX'></th></span></q></dt></tr></i><div id='kzGIX'><tfoot id='kzGIX'></tfoot><dl id='kzGIX'><fieldset id='kzGIX'></fieldset></dl></div>

      2. 在 Json.net 中使用自定义 JsonConverter 和 TypeNameHan

        时间:2023-08-23

        <small id='k28tT'></small><noframes id='k28tT'>

          <legend id='k28tT'><style id='k28tT'><dir id='k28tT'><q id='k28tT'></q></dir></style></legend>

                  <tbody id='k28tT'></tbody>
                <i id='k28tT'><tr id='k28tT'><dt id='k28tT'><q id='k28tT'><span id='k28tT'><b id='k28tT'><form id='k28tT'><ins id='k28tT'></ins><ul id='k28tT'></ul><sub id='k28tT'></sub></form><legend id='k28tT'></legend><bdo id='k28tT'><pre id='k28tT'><center id='k28tT'></center></pre></bdo></b><th id='k28tT'></th></span></q></dt></tr></i><div id='k28tT'><tfoot id='k28tT'></tfoot><dl id='k28tT'><fieldset id='k28tT'></fieldset></dl></div>
                <tfoot id='k28tT'></tfoot>

                  <bdo id='k28tT'></bdo><ul id='k28tT'></ul>
                • 本文介绍了在 Json.net 中使用自定义 JsonConverter 和 TypeNameHandling的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                  问题描述

                  我有一个具有接口类型属性的类,例如:

                  I have a class with an interface-typed property like:

                  public class Foo
                  {
                      public IBar Bar { get; set; }
                  }
                  

                  我还有多个可以在运行时设置的IBar 接口的具体实现.其中一些具体类需要一个自定义的 JsonConverter 来进行序列化和反序列化.

                  I also have multiple concrete implementations of the IBar interface that can be set at runtime. Some of these concrete classes require a custom JsonConverter for serialization & deserialization.

                  利用 TypeNameHandling.Auto 选项可以完美地序列化和反序列化需要 IBar 类的非转换器.另一方面,自定义序列化的类没有 $type 名称输出,虽然它们按预期序列化,但它们不能反序列化为它们的具体类型.

                  Utilizing the TypeNameHandling.Auto option the non-convertor requiring IBar classes can be serialized and deserialized perfectly. The custom-serialized classes on the other hand have no $type name output and while they are serialized as expected, they cannot be deserialized to their concrete type.

                  我尝试在自定义 JsonConverter 中自己写出 $type 名称元数据;但是,在反序列化时,转换器将被完全绕过.

                  I attempted to write-out the $type name metadata myself within the custom JsonConverter; however, on deserialization the converter is then being bypassed entirely.

                  是否有解决方法或适当的方法来处理这种情况?

                  Is there a workaround or proper way of handling such a situation?

                  推荐答案

                  我解决了类似的问题,我找到了解决方案.它不是很优雅,我认为应该有更好的方法,但至少它有效.所以我的想法是每个实现 IBar 的类型都有 JsonConverterIBar 本身的转换器.

                  I solved the similar problem and I found a solution. It's not very elegant and I think there should be a better way, but at least it works. So my idea was to have JsonConverter per each type that implements IBar and one converter for IBar itself.

                  让我们从模型开始:

                  public interface IBar { }
                  
                  public class BarA : IBar  { }
                  
                  public class Foo
                  {
                      public IBar Bar { get; set; }
                  }
                  

                  现在让我们为 IBar 创建转换器.仅在反序列化 JSON 时使用.它将尝试读取 $type 变量并调用转换器以实现类型:

                  Now let's create converter for IBar. It will be used only when deserializing JSON. It will try to read $type variable and call converter for implementing type:

                  public class BarConverter : JsonConverter
                  {
                      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
                      {
                          throw new NotSupportedException();
                      }
                  
                      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
                      {
                          var jObj = JObject.Load(reader);
                          var type = jObj.Value<string>("$type");
                  
                          if (type == GetTypeString<BarA>())
                          {
                              return new BarAJsonConverter().ReadJson(reader, objectType, jObj, serializer);
                          }
                          // Other implementations if IBar
                  
                          throw new NotSupportedException();
                      }
                  
                      public override bool CanConvert(Type objectType)
                      {
                          return objectType == typeof (IBar);
                      }
                  
                      public override bool CanWrite
                      {
                          get { return false; }
                      }
                  
                      private string GetTypeString<T>()
                      {
                          var typeOfT = typeof (T);
                          return string.Format("{0}, {1}", typeOfT.FullName, typeOfT.Assembly.GetName().Name);
                      }
                  }
                  

                  这是 BarA 类的转换器:

                  public class BarAJsonConverter : BarBaseJsonConverter
                  {
                      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
                      {
                          // '$type' property will be added because used serializer has TypeNameHandling = TypeNameHandling.Objects
                          GetSerializer().Serialize(writer, value);
                      }
                  
                      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
                      {
                          var existingJObj = existingValue as JObject;
                          if (existingJObj != null)
                          {
                              return existingJObj.ToObject<BarA>(GetSerializer());
                          }
                  
                          throw new NotImplementedException();
                      }
                  
                      public override bool CanConvert(Type objectType)
                      {
                          return objectType == typeof(BarA);
                      }
                  }
                  

                  您可能会注意到它继承自 BarBaseJsonConverter 类,而不是 JsonConverter.而且我们在 WriteJsonReadJson 方法中不使用 serializer 参数.在自定义转换器中使用 serializer 参数存在问题.你可以阅读更多这里.我们需要创建 JsonSerializer 的新实例,而基类是一个很好的候选对象:

                  You may notice that it's inherited from BarBaseJsonConverter class, not JsonConverter. And also we do not use serializer parameter in WriteJson and ReadJson methods. There is a problem with using serializer parameter inside custom converters. You can read more here. We need to create new instance of JsonSerializer and base class is a good candidate for that:

                  public abstract class BarBaseJsonConverter : JsonConverter
                  {
                      public JsonSerializer GetSerializer()
                      {
                          var serializerSettings = JsonHelper.DefaultSerializerSettings;
                          serializerSettings.TypeNameHandling = TypeNameHandling.Objects;
                  
                          var converters = serializerSettings.Converters != null
                              ? serializerSettings.Converters.ToList()
                              : new List<JsonConverter>();
                          var thisConverter = converters.FirstOrDefault(x => x.GetType() == GetType());
                          if (thisConverter != null)
                          {
                              converters.Remove(thisConverter);
                          }
                          serializerSettings.Converters = converters;
                  
                          return JsonSerializer.Create(serializerSettings);
                      }
                  }
                  

                  JsonHelper只是一个创建JsonSerializerSettings的类:

                  public static class JsonHelper
                  {
                      public static JsonSerializerSettings DefaultSerializerSettings
                      {
                          get
                          {
                              return new JsonSerializerSettings
                              {
                                  Converters = new JsonConverter[] { new BarConverter(), new BarAJsonConverter() }
                              };
                          }
                      }
                  }
                  

                  现在它可以工作了,您仍然可以使用自定义转换器进行序列化和反序列化:

                  Now it will work and you still can use your custom converters for both serialization and deserialization:

                  var obj = new Foo { Bar = new BarA() };
                  var json = JsonConvert.SerializeObject(obj, JsonHelper.DefaultSerializerSettings);
                  var dObj = JsonConvert.DeserializeObject<Foo>(json, JsonHelper.DefaultSerializerSettings);
                  

                  这篇关于在 Json.net 中使用自定义 JsonConverter 和 TypeNameHandling的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                  上一篇:BinaryFormatter 怎么可以序列化一个 Action&lt;&am 下一篇:C# JsonConvert 使用默认转换器而不是自定义转换器

                  相关文章

                  最新文章

                      <bdo id='DLI2y'></bdo><ul id='DLI2y'></ul>

                  1. <small id='DLI2y'></small><noframes id='DLI2y'>

                    <i id='DLI2y'><tr id='DLI2y'><dt id='DLI2y'><q id='DLI2y'><span id='DLI2y'><b id='DLI2y'><form id='DLI2y'><ins id='DLI2y'></ins><ul id='DLI2y'></ul><sub id='DLI2y'></sub></form><legend id='DLI2y'></legend><bdo id='DLI2y'><pre id='DLI2y'><center id='DLI2y'></center></pre></bdo></b><th id='DLI2y'></th></span></q></dt></tr></i><div id='DLI2y'><tfoot id='DLI2y'></tfoot><dl id='DLI2y'><fieldset id='DLI2y'></fieldset></dl></div>
                    <legend id='DLI2y'><style id='DLI2y'><dir id='DLI2y'><q id='DLI2y'></q></dir></style></legend>

                    <tfoot id='DLI2y'></tfoot>