Как сериализовать json, чтобы отображать значение свойства вместо имени свойства?

Я пытаюсь найти способ сериализовать объект в строку json в следующем формате, чтобы соответствовать требованиям проекта.

{
  "id": 123456,
  "los": {
    "2019-05-13": [
      {
        "currency": "EUR",
        "guests": 2,
        "price": [
          100,
          200
        ]
      },
      {
        "currency": "EUR",
        "guests": 3,
        "price": [
          150,
          250
        ]
      }
    ],
    "2019-05-14": {
      "currency": "EUR",
      "guests": 2,
      "price": [
        300
      ]
    }
  },
}

Я создал эти классы моделей:

public class Rootobject
{
    public Los los { get; set; }
    public int Id { get; set; }
}

public class Los
{
    public Item[] items{ get; set; }
}

public class Item
{
    public DateTime date {get;set;}
    public string currency { get; set; }
    public int guests { get; set; }
    public int[] price { get; set; }
}

Можно каким-то образом изменить имя элемента во время сериализации, поэтому Item сериализуется как «2019-05-13», «2019-05-14» и т. д.?


person mko    schedule 10.01.2020    source источник
comment
Точно так же, как вы сериализуете его: сохраните элементы в словаре, где строка даты является ключом. Если вы этого не хотите, вы пишете собственный модуль форматирования, который делает это, так что это действительно долгий путь, не используя соответствующую структуру данных.   -  person CodeCaster    schedule 10.01.2020
comment
имеет смысл, позвольте мне попробовать   -  person mko    schedule 10.01.2020
comment
Советы для профессионалов: если имя свойства является значением, то это словарь. Чтобы обеспечить уникальность ключа, словарь сериализуется как объект, где ключ — это имя свойства, а значение — значение свойства.   -  person xdtTransform    schedule 10.01.2020
comment
Также предоставьте образец вывода, который вы ожидаете увидеть   -  person Jawad    schedule 10.01.2020
comment
Для этого вы можете использовать Json.Linq, как в этой теме Получение имя/ключ JToken с JSON.net   -  person Pavel Anikhouski    schedule 10.01.2020
comment
@CodeCaster это должно работать, но у меня проблемы с тем, чтобы скрыть элемент из строки json. Я попытался добавить [JsonExtensionData] перед свойством items, но это работает только с IDictionary‹string, JToken›   -  person mko    schedule 10.01.2020
comment
Удалите класс Los вообще, сделайте свойство los RootObject типа Dictionary<string, Item> и оно будет работать?   -  person CodeCaster    schedule 11.01.2020


Ответы (1)


Для этого вам понадобится такая структура класса:

public class Rootobject
{
    public int Id { get; set; }
    [JsonConverter(typeof(CustomItemConverter))]
    public Dictionary<DateTime, Item[]> Los { get; set; }
}

public class Item
{
    [JsonIgnore]
    public DateTime Date { get; set; }
    public string Currency { get; set; }
    public int Guests { get; set; }
    public int[] Price { get; set; }
}

и пользовательский конвертер:

public class CustomItemConverter : JsonConverter
{
    public override bool CanRead => false;

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Dictionary<DateTime, Item[]>);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var dictionary = (Dictionary<DateTime, Item[]>)value;

        writer.WriteStartArray();
        foreach (var item in dictionary)
        {
            writer.WriteStartObject();
            writer.WritePropertyName(item.Key.Date.ToString("yyyy-MM-dd"));
            serializer.Serialize(writer, item.Value);
            writer.WriteEndObject();
        }
        writer.WriteEndArray();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
    }
}
person smolchanovsky    schedule 10.01.2020
comment
Зачем мне нужен CustomItemConverter? - person mko; 10.01.2020
comment
Пользовательский преобразователь позволяет переопределить сериализацию, чтобы добавить свойство ключей. документ - person smolchanovsky; 10.01.2020
comment
Да, это хорошо и все такое, но пользовательский преобразователь добавляет проблему ремонтопригодности. Что, если они захотят сериализовать несколько свойств нескольких классов, как это? Вам придется ввести дженерики, и если вы захотите десериализовать тот же JSON, у вас будет еще больше работы. - person CodeCaster; 11.01.2020