JSON.NET от Newtonsoft не сериализует свойства типов `IEnumerable` [duplicate]

Это потому, что, когда вы вводите номер, нажмите «Ввод», input.nextInt() потребляет только номер, а не «конец строки». Когда input.nextLine() выполняется, он потребляет «конец строки» все еще в буфере с первого входа.

Вместо этого используйте input.nextLine() сразу после input.nextInt()

6
задан Brian Rogers 9 September 2015 в 14:49
поделиться

2 ответа

По умолчанию Json.Net будет обрабатывать любой класс, который реализует IEnumerable как массив. Вы можете переопределить это поведение, украсив класс атрибутом [JsonObject], но тогда только свойства объекта будут сериализованы, как вы видели. Сам список не будет сериализован, потому что он не открывается через общедоступный объект (скорее, он отображается через метод GetEnumerator()).

Если вы хотите оба, вы можете либо сделать, как @Konrad предложили и предоставили публичную собственность на ваш производный класс, чтобы открыть список, или вы можете написать пользовательский JsonConverter, чтобы сериализовать все, как вам кажется. Ниже приведен пример последнего подхода.

Предполагая, что ваш класс PagedResult<T> выглядит примерно так:

class PagedResult<T> : List<T>
{
    public int PageSize { get; set; }
    public int PageIndex { get; set; }
    public int TotalItems { get; set; }
    public int TotalPages { get; set; }
}

Вы можете сделать для него такой конвертер:

class PagedResultConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(PagedResult<T>));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        PagedResult<T> result = (PagedResult<T>)value;
        JObject jo = new JObject();
        jo.Add("PageSize", result.PageSize);
        jo.Add("PageIndex", result.PageIndex);
        jo.Add("TotalItems", result.TotalItems);
        jo.Add("TotalPages", result.TotalPages);
        jo.Add("Items", JArray.FromObject(result.ToArray(), serializer));
        jo.WriteTo(writer);
    }

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

(Обратите внимание также, что атрибуты [JsonObject] и [JsonProperty] не требуются при таком подходе, поскольку знание того, что сериализовать, инкапсулируется в класс преобразователя.)

Здесь представляет собой демонстрацию, показывающую преобразователь в действии:

class Program
{
    static void Main(string[] args)
    {
        PagedResult<string> result = new PagedResult<string> { "foo", "bar", "baz" };
        result.PageIndex = 0;
        result.PageSize = 10;
        result.TotalItems = 3;
        result.TotalPages = 1;

        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.Converters.Add(new PagedResultConverter<string>());
        settings.Formatting = Formatting.Indented;

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

Выход:

{
  "PageSize": 10,
  "PageIndex": 0,
  "TotalItems": 3,
  "TotalPages": 1,
  "Items": [
    "foo",
    "bar",
    "baz"
  ]
}
4
ответ дан Brian Rogers 26 August 2018 в 13:57
поделиться

Самое простое решение, которое приходит мне на ум, состоит в том, чтобы выставить внутренние элементы как другое свойство производного класса:

[JsonProperty]
public IEnumerable<T> Elements {
    get 
    { 
       return this; 
    }
}
3
ответ дан Konrad Kokosa 26 August 2018 в 13:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: