2015-04-30 5 views
2

Мне нужно сериализовать объекты (OpenTK.Vector2), содержащие свойства с геттером, но без сеттера. Я хотел бы, чтобы эти свойства игнорировались вообще, в противном случае я получаю чрезвычайно завышенный JSON от объекта, который имеет две соответствующие части данных (X и Y).Не сериализуйте свойства без сеттера

Код:

JsonSerializerSettings settings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; 
Vector2 v = new Vector2 { X = 1, Y = 0 }; 
string json = JsonConvert.SerializeObject(v, settings); 

производит строку:

{ 
    "X" : 1.0, 
    "Y" : 0.0, 
    "Length" : 1.0, 
    "LengthFast" : 1.0016948, 
    "LengthSquared" : 1.0, 
    "PerpendicularRight" : { 
     "X" : 0.0, 
     "Y" : -1.0, 
     "Length" : 1.0, 
     "LengthFast" : 1.0016948, 
     "LengthSquared" : 1.0, 
     "PerpendicularRight" : { 
     "X" : -1.0, 
     "Y" : 0.0, 
     "Length" : 1.0, 
     "LengthFast" : 1.0016948, 
     "LengthSquared" : 1.0, 
     "PerpendicularRight" : { 
      "X" : 0.0, 
      "Y" : 1.0, 
      "Length" : 1.0, 
      "LengthFast" : 1.0016948, 
      "LengthSquared" : 1.0 
     } 
     }, 
     "Yx" : { 
     "X" : -1.0, 
     "Y" : 0.0, 
     "Length" : 1.0, 
     "LengthFast" : 1.0016948, 
     "LengthSquared" : 1.0, 
     "PerpendicularRight" : { 
      "X" : 0.0, 
      "Y" : 1.0, 
      "Length" : 1.0, 
      "LengthFast" : 1.0016948, 
      "LengthSquared" : 1.0 
     } 
     } 
    }, 
    "PerpendicularLeft" : { 
     "X" : 0.0, 
     "Y" : 1.0, 
     "Length" : 1.0, 
     "LengthFast" : 1.0016948, 
     "LengthSquared" : 1.0, 
     "PerpendicularLeft" : { 
     "X" : -1.0, 
     "Y" : 0.0, 
     "Length" : 1.0, 
     "LengthFast" : 1.0016948, 
     "LengthSquared" : 1.0, 
     "PerpendicularLeft" : { 
      "X" : 0.0, 
      "Y" : -1.0, 
      "Length" : 1.0, 
      "LengthFast" : 1.0016948, 
      "LengthSquared" : 1.0 
     }, 
     "Yx" : { 
      "X" : 0.0, 
      "Y" : -1.0, 
      "Length" : 1.0, 
      "LengthFast" : 1.0016948, 
      "LengthSquared" : 1.0 
     } 
     } 
    }, 
    "Yx" : { 
     "X" : 0.0, 
     "Y" : 1.0, 
     "Length" : 1.0, 
     "LengthFast" : 1.0016948, 
     "LengthSquared" : 1.0, 
     "PerpendicularLeft" : { 
     "X" : -1.0, 
     "Y" : 0.0, 
     "Length" : 1.0, 
     "LengthFast" : 1.0016948, 
     "LengthSquared" : 1.0, 
     "PerpendicularLeft" : { 
      "X" : 0.0, 
      "Y" : -1.0, 
      "Length" : 1.0, 
      "LengthFast" : 1.0016948, 
      "LengthSquared" : 1.0 
     }, 
     "Yx" : { 
      "X" : 0.0, 
      "Y" : -1.0, 
      "Length" : 1.0, 
      "LengthFast" : 1.0016948, 
      "LengthSquared" : 1.0 
     } 
     } 
    } 
} 

Как я могу получить сериализатор игнорировать эти другие свойства?

+0

На самом деле мне трудно описать логику вывода. Дерево для 'PerpendicularRight' включает в себя' PerpendicularLeft' и наоборот. – AbleArcher

ответ

4

Поскольку вы не можете изменить OpenTK.Vector2-структуру, чтобы добавить [JsonIgnore] свойство ГЭТ только свойства, самый простой способ сделать это может быть, чтобы написать свой собственный JsonConverter для него:

public class Vector2Converter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(OpenTK.Vector2); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var temp = JObject.Load(reader); 
     return new OpenTK.Vector2(((float?)temp["X"]).GetValueOrDefault(), ((float?)temp["Y"]).GetValueOrDefault()); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var vec = (OpenTK.Vector2)value; 
     serializer.Serialize(writer, new { X = vec.X, Y = vec.Y}); 
    } 
} 

Затем используйте его как:

 var settings = new JsonSerializerSettings(); 
     settings.Converters.Add(new Vector2Converter()); 
     Vector2 v = new Vector2 { X = 1, Y = 0 }; 
     string json = JsonConvert.SerializeObject(v, settings); 
     Debug.WriteLine(json); 

Который производит

{"X":1.0,"Y":0.0} 

Но если вы действительно хотите игнорировать все свойства get-only во всех классах и структурах (что может иметь непредвиденные последствия), см. Здесь: Is there a way to ignore get-only properties in Json.NET without using JsonIgnore attributes?.

+0

Идеальный ответ. Спасибо за ваше время. – AbleArcher

+0

Если я использую 'JsonConverter' в сочетании с' ContractResolver', описанным в ссылке, то я вообще не получаю никакого вывода. В этом случае метод «CreateProperties» вызывается дважды, второй раз с некоторым анонимным типом, для которого он возвращает пустой список. – AbleArcher

+1

@thethuthinnang - это, вероятно, потому, что все анонимные типы, такие как тот, который я сериализую с помощью 'new {X = vec.X, Y = vec.Y}' [не имеют сеттеров] (https://stackoverflow.com/questions/1089406/почему-это-то-свойства-на-анонимных-типов-в-с-диез-только для чтения). – dbc

Смежные вопросы