2016-11-18 4 views
1

Я хочу изменить тип свойства из массива в объект с помощью JsonConverter. Например, у меня есть свойство [{"Name":"aaa"}]. После сериализации я хочу получить такой результат: {"__po":"Add",Objects:[{"Name":"aaa"}]}.Как преобразовать массив в объект в JsonConverter

Так что я создал класс для настройки моего сериалайзера:

public class Serializer : ISerializer 
{ 
    public JsonSerializerSettings SerializerSettings { get; set; } 

    public Serializer() 
    { 
     SerializerSettings = new JsonSerializerSettings(); 
     SerializerSettings.Converters.Add(new ParseArrayToObjectJsonConverter()); 
    } 

    public class ParseArrayToObjectJsonConverter : JsonConverter 
    { 
     public override bool CanConvert(Type objectType) 
     { 
      if (objectType.GetTypeInfo().Name.EndsWith("Array")) 
      { 
       return true; 
      } 
      return false; 
     } 

     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 

     } 
    } 
} 

Я вижу, что JsonWriter обладает этим свойством public WriteState WriteState { get; }, который может вернуть перечисление как это: public enum WriteState { Error = 0, Closed = 1, Object = 2, Array = 3, Constructor = 4, Property = 5, Start = 6 }.

В моем методе WriteJson, тип writer.WriteState является WriteState.Array, но проблема в том, что я не могу установить значение WriteState для возвращения объекта. Есть ли у вас какие-либо другие решения для решения этой проблемы?

+0

JsonWriter имеет это свойство public WriteState WriteState {get; }, Который может вернуть перечисление как этот «перечислений WriteState общественного { Error = 0, Closed = 1, Object = 2, Array = 3, Constructor = 4, Property = 5, Start = 6 } 'в моем случае значение Writer.WriteState является WriteState.Array, но проблема я не могу установить значение Writer.WriteState для возврата объекта. –

ответ

1

Я думаю, что вы не понимаете, как использовать JsonWriter в пределах JsonConverter. Вам не нужно будет возиться с писателем WriteState. Это свойство только для чтения, которое указывает, что писатель в настоящее время пишет. Вы не можете изменить его напрямую. Вместо этого вы должны использовать методы писателя WriteXxx(), чтобы фактически выписать JSON, который вы хотите. Вот как вы бы реализовать JsonConverter, который оборачивает массив в объекте:

public class WrapArrayInObjectJsonConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     // This will cause the converter to wrap ALL IEnumerables (except strings) in an object. 
     return typeof(IEnumerable).IsAssignableFrom(objectType) && objectType != typeof(string); 

     // If you only want to this converter to wrap specific kinds of arrays, change this 
     // method accordingly. For example, this will only wrap Foo[] or List<Foo>: 
     //return typeof(IEnumerable<Foo>).IsAssignableFrom(objectType); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     IEnumerable array = (IEnumerable)value; 
     writer.WriteStartObject(); 
     writer.WritePropertyName("__po"); 
     writer.WriteValue("Add"); 
     writer.WritePropertyName("Objects"); 
     writer.WriteStartArray(); 
     foreach (object item in array) 
     { 
      serializer.Serialize(writer, item); 
     } 
     writer.WriteEndArray(); 
     writer.WriteEndObject(); 
    } 

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

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

Вот пример использования конвертера:

Foo[] array = new Foo[] 
{ 
    new Foo { Name = "aaa" }, 
    new Foo { Name = "bbb" } 
}; 

JsonSerializerSettings settings = new JsonSerializerSettings(); 
settings.Converters.Add(new WrapArrayInObjectJsonConverter()); 

string json = JsonConvert.SerializeObject(array, settings); 
Console.WriteLine(json); 

Выход:

{"__po":"Add","Objects":[{"Name":"aaa"},{"Name":"bbb"}]} 

Fiddle: https://dotnetfiddle.net/79mXF2

+0

Это именно то, что мне нужно. Спасибо, очень милый мистер @Brian :) –