2014-12-14 2 views
1

я пытаюсь повторить следующую структуру JSON:Создание JSON с динамическими ключами в C#

{"result_content": { 
    "data": { 
     "city_name" : "Beverly Hills", 
     "2014-06-05T00:00:00": { 
     "morning_low": "20", 
     "daytime_high": "40" 
     }, 
     "2014-06-06T00:00:00": { 
     "morning_low": "21", 
     "daytime_high": "41" 
     }, 
     "2014-06-07T00:00:00": { 
     "morning_low": "22", 
     "daytime_high": "42" 
     }, 
     "2014-06-08T00:00:00": { 
     "morning_low": "23", 
     "daytime_high": "43" 
     }, 
     "2014-06-09T00:00:00": { 
     "morning_low": "24", 
     "daytime_high": "44" 
     } 
     } 
    } 
    } 

Но я не могу понять, как создавать ключи быть динамическим, используя C#.

Вот мой объект класса

public class Day 
{ 
    public string morning_low { get; set; } 
    public string daytime_high { get; set; } 
} 

public class Data 
{ 
    public string city_name { get; set; } 
    public List<Day> days { get; set; } 
} 

public class ResultContent 
{ 
    public Data data { get; set; } 
} 

А вот как им здание все:

  ResultContent content = new ResultContent(); 
      content.data = new Data(); 
      content.data.city_name = results.Body.GetCityForecastByZIPResponse.GetCityForecastByZIPResult.City; 

      foreach (Forecast day in results.Body.GetCityForecastByZIPResponse.GetCityForecastByZIPResult.ForecastResult.Forecast){ 
       Day x = new Day(); 
       x.daytime_high = day.Temperatures.DaytimeHigh; 
       x.morning_low = day.Temperatures.MorningLow; 
       content.data.days.Add(x); 
      } 

      return JsonConvert.SerializeObject(content); 

Это просто возвращает массив JSON дней, который не то, что я хочу. У меня есть DateTime в моем объекте результатов.

+1

является "2014-06-05T00: 00: 00" действительным именем? – Igor

+0

Это штамп datetime – user2901304

+0

Я вижу, что это такое, это был не мой вопрос – Igor

ответ

1

Если вы действительно хотите такой сложный формат, я бы с обычаем JsonConverter:

public class Day 
{ 
    public string morning_low { get; set; } 
    public string daytime_high { get; set; } 
} 

[JsonConverter(typeof(Data.Converter))] 
public class Data 
{ 
    public string city_name { get; set; } 
    public Dictionary<DateTime, Day> days { get; set; } 

    public class Converter : JsonConverter 
    { 
     public override bool CanConvert(Type type) { return type == typeof(Data); } 
     public override object ReadJson(JsonReader reader, Type type, object value, JsonSerializer serializer) 
     { 
      Data obj = new Data(); 
      obj.days = new Dictionary<DateTime, Day>(); 
      DateTime v; 
      while (reader.Read() && reader.TokenType != JsonToken.EndObject) 
      { 
       if (reader.TokenType != JsonToken.PropertyName) 
        throw new JsonSerializationException("Unexpected token type"); 

       if ("city_name" == (string)reader.Value) 
       { 
        if (obj.city_name != null) 
         throw new JsonSerializationException("Duplicate key: city_name"); 
        obj.city_name = reader.ReadAsString(); 
       } 
       else if (DateTime.TryParseExact((string)reader.Value, serializer.DateFormatString, 
               serializer.Culture, DateTimeStyles.None, out v)) 
       { 
        reader.Read(); 
        obj.days.Add(v, serializer.Deserialize<Day>(reader)); 
       } 
       else 
       { 
        if (serializer.MissingMemberHandling == MissingMemberHandling.Error) 
         throw new JsonSerializationException("Unexpected property: " + reader.Value); 
        reader.Read(); 
        serializer.Deserialize(reader, reader.ValueType); 
       } 
      } 
      return obj; 
     } 
     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      Data obj = (Data)value; 
      writer.WriteStartObject(); 
      writer.WritePropertyName("city_name"); 
      writer.WriteValue(obj.city_name); 
      foreach (var pair in obj.days) 
      { 
       writer.WritePropertyName(pair.Key.ToString(serializer.DateFormatString)); 
       serializer.Serialize(writer, pair.Value); 
      } 
      writer.WriteEndObject(); 
     } 
    } 
} 

public class ResultContent 
{ 
    public Data data { get; set; } 
} 

public class ResultContentRoot 
{ 
    public ResultContent result_content { get; set; } 
} 

public static void Main() 
{ 
    var data = new Data(); 
    data.city_name = "New York"; 
    data.days = new Dictionary<DateTime, Day>(); 
    data.days.Add(DateTime.Today, new Day() { morning_low = "24", daytime_high = "29" }); 

    var result_content = new ResultContent(); 
    result_content.data = data; 

    var root = new ResultContentRoot(); 
    root.result_content = result_content; 

    var s = JsonConvert.SerializeObject(root); 
} 

Я думаю, что это единственный способ смешать словарь и объектные контракты.

Если вам нужна только односторонняя сериализация, вы также можете перейти с dynamic. Она занимает меньше кода:

public class Day 
{ 
    public string morning_low { get; set; } 
    public string daytime_high { get; set; } 
} 

public class ResultContent 
{ 
    public dynamic data { get; set; } 
} 

public class ResultContentRoot 
{ 
    public ResultContent result_content { get; set; } 
} 

public static void Main() 
{ 
    dynamic data = new ExpandoObject(); 
    data.city_name = "New York"; 
    IDictionary<string, object> days = (IDictionary<string, object>)data; 
    days.Add(DateTime.Today.ToString("yyyy-MM-dd'T'HH:mm:ss"), new Day() { morning_low = "24", daytime_high = "29" }); 

    var result_content = new ResultContent(); 
    result_content.data = data; 

    var root = new ResultContentRoot(); 
    root.result_content = result_content; 

    var s = JsonConvert.SerializeObject(root); 
} 

Но это очень близко, чтобы отменить все, что сильной типизации и просто построить ответ с JObject с.

+0

Спасибо, я закончил использование первого решения, но теперь у меня возникла другая проблема. Как черт может десериализировать это. – user2901304

+0

Обновлен код конвертера с реализацией 'ReadJson', поэтому теперь он поддерживает десериализацию. Возможно, не все возможные ошибки ввода проверяются, но они работают для действительного json. –

1

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

Они, как вы определили, должны производить что-то вроде этого ниже.

{ 
    "result_content": { 
     "data": { 
      "city_name" : "Beverly Hills", 
      "days" : 
      [ 
       { 
        "morning_low": "20", 
        "daytime_high": "40" 
       }, 
       { 
        "morning_low": "21", 
        "daytime_high": "41" 
       }, 
       { 
        "morning_low": "22", 
        "daytime_high": "42" 
       }, 
       { 
        "morning_low": "23", 
        "daytime_high": "43" 
       }, 
       { 
        "morning_low": "24", 
        "daytime_high": "44" 
       } 
      ] 
     } 
    } 
} 

Что вы пропустили это сам день, который должен быть определен в вашем Day классе. Добавьте его получить:

"days" : 
[ 
    { 
     "day" : "2014-06-05T00:00:00", 
     "morning_low": "20", 
     "daytime_high": "40" 
    } 
    ... 
] 
+0

Я полностью согласен, его чище, проще кодировать, а также дает возможность итерации через него легко и делать материал с данными, но мой босс хочет этого, к сожалению, другим способом. Я возражал против этого, но он не слушает – user2901304

0

Это, вероятно, что вы ищете в этом случае ...

void Main() 
{ 
    Result result = new Result 
    { 
     Data = new Data 
     { 
      WeatherData = new List<City> 
      { 
       new City 
       { 
        Name = "London", 
        Temp = new Dictionary<DateTime, TemperatureRange> 
        { 
         { 
          DateTime.UtcNow, 
          new TemperatureRange 
          { 
           DayHigh = 0, 
           MorningLow = 50 
          } 
         } 
        } 
       } 
      } 
     }  
    }; 

    JsonConvert.SerializeObject(result); 
} 

public class Result 
{ 
    [JsonProperty("result_content")] 
    public Data Data { get; set; } 
} 

public class Data 
{ 
    [JsonProperty("data")] 
    public List<City> WeatherData { get; set; } 
} 

public class City 
{ 
    [JsonProperty("city_name")] 
    public string Name { get; set; } 

    public Dictionary<DateTime, TemperatureRange> Temp { get; set; } 
} 

public class TemperatureRange 
{ 
    public int MorningLow { get; set; } 
    public int DayHigh { get; set; } 
} 
Смежные вопросы