Получение преобразователей, указанных через атрибуты, эквивалентно глобальным в json.net - PullRequest
0 голосов
/ 28 июня 2018

Когда using Newtonsoft.Json, я могу заставить его делать то, что мне нужно, добавив конвертер на верхний уровень SerializerSettings или поставив его в вызов преобразования - все работает хорошо.

Я надеюсь извлечь некоторые из моих глобальных конвертеров, которые вместо этого будут декларативно применяться в соответствующем месте, где конвертация действительно требуется.

Мне известны следующие техники: -

  • тип уровня [JsonConverter(typeof(Converters.StringEnumConverter))] непосредственно на тип X
  • уровень участника [JsonConverter(typeof(Converters.StringEnumConverter))] если член имеет тип X
  • уровень предмета [JsonProperty(ItemConverterType=typeof(Converters.StringEnumConverter)], если элемент на самом деле является массивом и т. Д. X

Проблема, с которой я сталкиваюсь, заключается в том, что некоторые глобальные конвертеры, которые я использую, работают с вложенными типами, например, если у меня есть член типа Tuple<X[],Nullable<X>>, я не могу выразить ", если вы встречаете X при обработке этого поля или любого его потомка, выполните преобразование" семантическое и вместо этого получите Newtonsoft.Json.JsonSerializationException .

Существует ли такой "для этого дерева, также используйте этот конвертер, пожалуйста" механизм существует? Я бы хотел избежать определения типа верхнего уровня для всего, что я когда-либо захочу преобразовать, а затем пометить этот тип с помощью JsonConverter, чтобы обойти это?

1 Ответ

0 голосов
/ 11 сентября 2018

Если я вас правильно понял и согласно официальным документам, вы можете применять конвертеры напрямую и фильтровать по типу, используя пользовательский конвертер:

SomeType someObject = new SomeType();
string json = JsonConvert.SerializeObject(someObject, Formatting.Indented, new MyCustomConverter(typeof(SomeType)));

public class MyCustomConverter : JsonConverter
{

     private readonly Type[] _types;

     public MyCustomConverter (params Type[] types)
     {
         _types = types;
     }

     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
         JToken t = JToken.FromObject(value);

         if (t.Type != JTokenType.Object)
         {
             t.WriteTo(writer);
         }
         else
         {
             JObject o = (JObject)t;
             IList<string> propertyNames = o.Properties().Select(p => p.Name).ToList();

             o.AddFirst(new JProperty("Keys", new JArray(propertyNames)));

             o.WriteTo(writer);
        }
     }

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
     {
          throw new NotImplementedException();
     }

     public override bool CanRead
     {
          get { return false; }
     }

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

Источник: https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm

...