I have this strange issue with parsing given JSON data. I have this JSON structure:
{\"value\":[
{\"street\":\"Karlova 25\"},
{\"city\":\"Prague\"},
{\
You don't need to reinvent the wheel. This funcionality is already working. Create classes like below:
public class Value
{
public string street { get; set; }
public string city { get; set; }
public string gpsLat { get; set; }
public string gpsLon { get; set; }
}
public class MyClass
{
public List<Value> value { get; set; }
}
Now You can simply deserialize your json to your poco object.
MyClass result = JsonConvert.DeserializeObject<MyClass>(youJson);
It appears that you want to represent a Dictionary<string, string>
in your JSON as an array of objects, where each nested object has one key and value from the dictionary. You can do it with the following converter:
public class DictionaryToDictionaryListConverter<TKey, TValue> : JsonConverter
{
class DictionaryDTO : Dictionary<TKey, TValue>
{
public DictionaryDTO(KeyValuePair<TKey, TValue> pair) : base(1) { Add(pair.Key, pair.Value); }
}
public override bool CanConvert(Type objectType)
{
return typeof(IDictionary<TKey, TValue>).IsAssignableFrom(objectType) && objectType != typeof(DictionaryDTO);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var token = JToken.Load(reader);
var dict = (IDictionary<TKey, TValue>)(existingValue as IDictionary<TKey, TValue> ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator());
if (token.Type == JTokenType.Array)
{
foreach (var item in token)
using (var subReader = item.CreateReader())
serializer.Populate(subReader, dict);
}
else if (token.Type == JTokenType.Object)
{
using (var subReader = token.CreateReader())
serializer.Populate(subReader, dict);
}
return dict;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var dict = (IDictionary<TKey, TValue>)value;
// Prevent infinite recursion of converters by using DictionaryDTO
serializer.Serialize(writer, dict.Select(p => new DictionaryDTO(p)));
}
}
Then use it in your container class as follows:
public class RootObject
{
[JsonProperty("value")]
[JsonConverter(typeof(DictionaryToDictionaryListConverter<string, string>))]
public Dictionary<string, string> Value { get; set; }
}
Note that the converter will throw an exception during reading if the keys are not unique.
Update
For AddressValue
you could use the following converter:
public class AddressValueConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(AddressValue);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var addressValue = (existingValue as AddressValue ?? new AddressValue());
var token = JObject.Load(reader);
var property = token.Properties().SingleOrDefault();
if (property != null)
{
addressValue.Label = property.Name;
addressValue.Value = (string)property.Value;
}
return addressValue;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var addressValue = (AddressValue)value;
serializer.Serialize(writer, new Dictionary<string, string> { { addressValue.Label, addressValue.Value } });
}
}
Then use it as follows:
[JsonConverter(typeof(AddressValueConverter))]
public class AddressValue
{
public string Label { get; set; }
public string Value { get; set; }
}
public class RootObject
{
[JsonProperty("value")]
public List<AddressValue> Value { get; set; }
}
Demo fiddle with both options here.