2014-02-07 7 views
2

У меня есть следующий класс (немного упрощенный вариант):Как преобразовать собственный класс списка в json?

public class DemoList<K, V> 
{ 
    private List<SomeItem<K, V>> _listItems; 

    public DemoList() 
    { 
     _listItems = new List<SomeItem<K, V>>(); 
    } 
    public Int32 Count 
    { 
     get { return _listItems.Count; } 
    } 
    public void Add(SomeItem<K, V> item) 
    { 
     _listItems.Add(item); 
    } 
    public SomeItem<K, V> this[int index] 
    { 
     get { return _listItems[index]; } 
    } 
} 

Код SomeItem:

public class SomeItem<K, V> 
{ 
    private K _key; 
    private V _value; 
    public SomeItem(K key, V value) 
    { 
     _key = key; 
     _value = value; 
    } 
    public K Key 
    { 
     get { return _key; } 
     set { _key = value; } 
    } 
    public V Value 
    { 
     get { return _value; } 
     set { _value = value; } 
    } 
} 

Когда я добавить некоторые значения в демонстрационном списке:

DemoList<String, String> dl = new DemoList<string, string>(); 
dl.Add(new SomeItem<string, string>("bla1", "diebla1")); 
dl.Add(new SomeItem<string, string>("bla2", "diebla2")); 
dl.Add(new SomeItem<string, string>("bla3", "diebla3")); 
dl.Add(new SomeItem<string, string>("bla4", "diebla4")); 

Теперь я хотел бы преобразовать это в json, используя NewtonSoft.Json ... вот так:

JsonSerializerSettings serializerSettings = new JsonSerializerSettings(); 
serializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
var jsonContent = JsonConvert.SerializeObject(dl, serializerSettings); 

Это приводит к следующему JSon:

{"Count":4} 

JSON Я надеялся на что-то вроде:

{ 
    "items": [ 
    { "bla1": "diabla1"}, 
    {"bla2": "diabla2"}, 
    {"bla3": "diabla3"}, 
    {"bla4": "diabla4"} 
    ] 
} 

Любые идеи?

+0

Я знаю, ссылки часто нахмурились, но http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size – RoughPlace

+0

Если быть честным, Я в последнее время возился с большим количеством JSON с C#, и мне было намного проще построить строку, чем пытаться использовать JSON.Net. Слишком много проблем, особенно когда я пытался получить JSON.Parse в JavaScript или Google Charts, чтобы узнать мои вещи. После того, как строка была построена, я просто очистил вызывающую страницу и напишу форматированный JSON. Если вам нравится эта идея, я отправлю фрагмент кода, где я это сделаю. –

ответ

3

Чтобы получить Json.Net сериализовать список элементов, вы можете выставить предметы, как публичной собственности (как и другие предложили), или пометить список с атрибутом [JsonProperty] следующим образом:

[JsonProperty("items")] 
    private List<SomeItem<K, V>> _listItems; 

Если вы хотите, чтобы подавить Count от выхода, отметить, что свойство с [JsonIgnore]:

[JsonIgnore] 
    public Int32 Count 
    { 
     get { return _listItems.Count; } 
    } 

с учетом указанных выше изменений, которые мы получаем следующий JSON, который ближе, но все же не совсем то, что вы хотели:

{ 
    "items": [ 
    { "key": "bla1", "value": "diebla1" }, 
    { "key": "bla2", "value": "diebla2" }, 
    { "key": "bla3", "value": "diebla3" }, 
    { "key": "bla4", "value": "diebla4" } 
    ] 
} 

Чтобы получить элементы в формат, который вы хотите, вам нужна пользовательский JsonConverter класса как это:

class SomeItemConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType.IsGenericType && 
      objectType.GetGenericTypeDefinition() == typeof(SomeItem<,>); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     JToken token = JToken.FromObject(value); 
     JObject obj = new JObject(); 
     obj.Add(token["Key"].ToString(), token["Value"]); 
     obj.WriteTo(writer); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     JToken token = JToken.Load(reader); 
     JProperty prop = token.Children<JProperty>().First(); 
     JObject obj = new JObject(); 
     obj.Add("Key", prop.Name); 
     obj.Add("Value", prop.Value); 
     return obj.ToObject(objectType); 
    } 
} 

Добавить конвертер к вашему JsonSerializerSettings и сериализация списка, как и раньше:

JsonSerializerSettings serializerSettings = new JsonSerializerSettings(); 
serializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
serializerSettings.Converters.Add(new SomeItemConverter()); 
var jsonContent = JsonConvert.SerializeObject(dl, serializerSettings); 
Console.WriteLine(jsonContent); 

Теперь у нас есть этот JSON:

{ 
    "items": [ 
     { "bla1":"diebla1" }, 
     { "bla2":"diebla2" }, 
     { "bla3":"diebla3" }, 
     { "bla4":"diebla4" } 
    ] 
} 
+0

Брайан ... спасибо миллион! Это действительно решает все проблемы. Я тестировал его, и он работает.Я не понимаю, как можно получить данные из частной собственности в json-файле, просто добавив [JsonProperty («items»)] ... _listItems IS private не так ли ??? Во всяком случае, как уже говорилось, он работает отлично! Он скрывает счет, он избегает необходимости создавать новые публичные объекты. Любить его! – Paul0515

+0

@ Paul0515 [Reflection] (http://msdn.microsoft.com/en-us/library/ms173183.aspx) позволяет «обманывать» и получать доступ к непубличным свойствам и методам объектов. Json.Net использует размышления для своего бизнеса, поэтому он работает. –

1

Создайте любой метод в DemoList, который возвращает _listItems. Тогда вызов этого метода getter в json serializer даст требуемый json.

+0

Это решает только часть проблемы. Ответчику нужны элементы в формате '{" foo ":" bar "}', а не '{" key ":" foo "," value ":" bar "}' format. –

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