2014-01-02 3 views
1

У меня есть объект C#. Я хочу сериализовать его на массив, а не на карту значения ключа.Сериализовать объект в массив

Мой C# класс:

[JsonArray()] 
public class Foo 
{ 
    [JsonProperty(Order = 1)] 
    public Boolean Bar = true; 

    [JsonProperty(Order = 2)] 
    public Boolean Baz = false; 
} 

Нужный выход JSON:

[true,false] 

Фактический выход JSON (если удалить атрибут JsonArray в верхней части):

{"Bar":true,"Baz":false} 

У меня есть большое количество объектов в сложной иерархии объектов, которые мне нужно сериализовать как массив, а карту значений ключа. Я бы предпочел решение, которое не требует, чтобы то, что делает сериализацию, ничего не знало о том, что оно сериализует. Я хочу, чтобы иметь возможность просто вызвать JsonConvert.SerializeObject (myThing) на объекте верхнего уровня и полностью сериализовать все под-объекты из-за атрибутов, которые они имеют на себе.

В настоящее время у меня есть все мои объекты, реализующие IEnumerable, а затем я вручную обучу каждому из них, как вернуть свойства в правильном порядке, но это вызывает путаницу при работе на C#, потому что intellisense пытается предложить мне все LINQ операции над объектом, хотя ни один из них не подходит.

Я считаю, что возможно, хотя я не знаю, как добавить атрибут к Foo, который указывает на другой класс, который знает, как сериализовать Foo. Что-то вроде [JsonConverter(FooSerializer)], а затем FooSerializer будет реализовывать JsonConverter. Тем не менее, я изо всех сил пытаюсь найти много информации о том, как использовать JsonConverter для сериализации, большинство вопросов, которые люди задают, похоже, связаны с десериализацией.

ответ

4

Вот как вы могли бы написать такой конвертер.

[JsonConverter(typeof(FooConverter))] 
public class Foo 
{ 
    public bool Bar { get; set; } 
    public bool Baz { get; set; } 
} 
public class FooConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var foo = value as Foo; 
     var obj = new object[] { foo.Bar, foo.Baz }; 
     serializer.Serialize(writer, obj); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var arr = ReadArrayObject(reader, serializer); 
     return new Foo 
     { 
      Bar = (bool)arr[0], 
      Baz = (bool)arr[1], 
     }; 
    } 

    private JArray ReadArrayObject(JsonReader reader, JsonSerializer serializer) 
    { 
     var arr = serializer.Deserialize<JToken>(reader) as JArray; 
     if (arr == null || arr.Count != 2) 
      throw new JsonSerializationException("Expected array of length 2"); 
     return arr; 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(Foo); 
    } 
} 

Когда речь идет о сериализации/десериализации, я считаю, что проще конвертировать в/из общего представления вашего объекта, сериализатор может распознавать и интерпретировать его по мере необходимости.

Сериализация (запись) была простой, поскольку вы хотели изменить представление своего объекта Foo на массив значений, преобразовать его в массив значений и сериализовать это.

Десериализация (чтение) может быть немного сложнее в целом. Но опять же, подход тот же. Вы ожидаете массив значений типа boolean. Уничтожьте массив и обработайте его, чтобы создать свой объект. Здесь вы можете выполнить некоторые проверки, если хотите, как я показал.

С этим вы можете легко конвертировать в строки JSON и из них.

var str = "[[true,true],[true,false]]"; 
var foos = JsonConvert.DeserializeObject<Foo[]>(str); 
var serialized = JsonConvert.SerializeObject(foos); 
Смежные вопросы