2

I am trying to find a way to serialize object to json string in the following format, so I can meet project requirements

{
  "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
      ]
    }
  },
}

I created these model classes:

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; }
}

It is possible somehow to change the name of an element during serialization, so Item is serialized as "2019-05-13", "2019-05-14" etc?

mko
  • 6,638
  • 12
  • 67
  • 118
  • 5
    Just the same way as you would serialize it: store the items in a dictionary, where the date string is the key. If you don't want this, you write a custom formatter that does this, so that's really going the long way around not using the appropriate data structure. – CodeCaster Jan 10 '20 at 13:03
  • makes sense, let me try – mko Jan 10 '20 at 13:06
  • Pro tips: if a properties name is a value then it's a dictionary. In order to enforce key uniqness, Dictionary are serialised as an object where the key are the property name and the value the property value. – xdtTransform Jan 10 '20 at 13:25
  • Also provide a sample output you expect to see – Jawad Jan 10 '20 at 13:25
  • You can use `Json.Linq` for that, like in this thread [Getting the name / key of a JToken with JSON.net](https://stackoverflow.com/questions/21002297/getting-the-name-key-of-a-jtoken-with-json-net) – Pavel Anikhouski Jan 10 '20 at 13:30
  • @CodeCaster this should work, but I am having trouble hiding "item" from json string. I tried adding [JsonExtensionData] in front of items property but this works only with IDictionary – mko Jan 10 '20 at 13:34
  • Remove the `Los` class altogether, make `RootObject`'s `los` property of type `Dictionary` and it will work? – CodeCaster Jan 11 '20 at 08:26

1 Answers1

1

To do this, you need this class structure:

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; }
}

and custom converter:

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.");
    }
}
smolchanovsky
  • 1,775
  • 2
  • 15
  • 29
  • Why would i need a CustomItemConverter? – mko Jan 10 '20 at 14:39
  • 1
    Custom converter allows to override serialization to add a keys property. [doc](https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm) – smolchanovsky Jan 10 '20 at 14:42
  • 1
    Yes that's fine and all, but a custom converter adds a maintainabilty problem. What if they want to serialize multiple properties of multiple classes like this? You'll have to introduce generics, and if you wan to _deserialize_ the same JSON, you'll have even more work to do. – CodeCaster Jan 11 '20 at 08:24