Reputation: 159
I have problems parsing Last.FM API JSON with JSON.NET. The problem is with string values that are meant to be null, like similar an tags in: http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=ASASAS&api_key=53aed44f6fa2ee83d40324232594e1d9&format=json
Otherwise, the object is well-formed: http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=Kamelot&api_key=53aed44f6fa2ee83d40324232594e1d9&format=json
[JsonConverter(typeof(StringNullConverter<Tags>))]
public class Tags
{
public List<Tag> tag { get; set; }
}
internal class StringVacioConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(string)) || (objectType == typeof(List<string>));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.String)
{
return null;
}
else { return serializer.Deserialize<T>(reader); }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
}
}
But this, is not working, it enters a infinite loop when tries to return serializer.Deserialize...
Upvotes: 2
Views: 807
Reputation: 116098
This code works for both of your json strings (only JsonConvert.DeserializeObject needs some help with a custom Converter (see the MyConverter below)).
var lastfm = LastFM.Deserialize(json);
public class LastFM
{
public class Image
{
[JsonProperty("#text")]
public string text { get; set; }
public string size { get; set; }
}
public class Stats
{
public string listeners { get; set; }
public string playcount { get; set; }
}
public class Similar
{
public List<Artist> artist { get; set; }
}
public class Tag
{
public string name { get; set; }
public string url { get; set; }
}
public class Tags
{
public List<Tag> tag { get; set; }
}
public class Link
{
[JsonProperty("#text")]
public string text { get; set; }
public string rel { get; set; }
public string href { get; set; }
}
public class Links
{
public Link link { get; set; }
}
public class Bio
{
public Links links { get; set; }
public string published { get; set; }
public string summary { get; set; }
public string content { get; set; }
}
public class Artist
{
public string name { get; set; }
public string mbid { get; set; }
public string url { get; set; }
public List<Image> image { get; set; }
public string streamable { get; set; }
public string ontour { get; set; }
public Stats stats { get; set; }
public Similar similar { get; set; }
public Tags tags { get; set; }
public Bio bio { get; set; }
}
public class RootObject
{
public Artist artist { get; set; }
}
public static RootObject Deserialize(string s)
{
return JsonConvert.DeserializeObject<RootObject>(s, new MyConverter());
}
class MyConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Similar) ||
objectType == typeof(Tags);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value is string && String.IsNullOrWhiteSpace((string)reader.Value)) return null;
return reader.Value;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}
Upvotes: 2
Reputation: 123851
Try to adjust your Converter like this:
// I. here we inherit from more sophisticated class, created for us
internal class StringNullConverter<T> : CustomCreationConverter<T>
where T : new()
{
// II. thanks the new() constraint we can override this method easily
public override T Create(Type objectType)
{
return new T();
}
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(string)) || (objectType == typeof(List<string>));
}
// III. here we pass the rest to smart base
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.String)
{
return null;
}
// this is the correct implementation
return base.ReadJson(reader, objectType, existingValue, serializer);
}
// unchanged
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
}
}
We do profit from full power of the Newtonsoft.Json
, which brings lot of pre-implemented stuff for us
Upvotes: 1