Reputation: 6994
I'm querying a service which returns a list of tags in multiple formats:
{
"tags": "a,b,c"
}
or
{
"tags": "a b c"
}
or
{
"tags": "a+b+c"
}
The object that I want to deserialize this to is a List<string>
. I've written a TagsConverter
that implements the necessary methods in JsonConverter
like so:
public class TagsConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(string));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return reader
.Value
.ToString()
.Split(' ')
.ToList();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var list = (List<string>)value;
var delimitedList = string.Join(" ", list);
writer.WriteValue(delimitedList);
}
}
Then I annotate the field in the object like so:
public class Foo
{
[JsonConverter(typeof(TagsConverter))]
public List<string> Tags { get; set; }
}
And this works, but only for tags that are separated by spaces.
However the TagsConverter
can work in all 3 scenarios if I'm able to just change the Split
and the Join
functions in a parameterized fashion. But since we pass only the type to the JsonConverter
attribute, I understand that we can't pass a "delimiter" as an argument there.
Is there any way to achieve this?
Upvotes: 3
Views: 1077
Reputation: 247098
If only needed for the reading/deserialization of the JSON do note that string.Split
can take a character array char[]
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return reader
.Value
.ToString()
.Split(new char[]{' ', ',', '+'}, StringSplitOptions.RemoveEmptyEntries)
.ToList();
}
Which means that the converter can handle all three delimiters when reading.
Upvotes: 2
Reputation: 33833
There is an additional JsonConverter
constructor overload that takes both a type and a params object[] converterParameters
that is injected into the concrete instance of your converter. You can take advantage of this overload to maximize your reusability.
public class TagsConverter : JsonConverter
{
private readonly string _delimiter;
public TagsConverter(string delimiter)
{
_delimiter = delimiter;
}
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(string));
}
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
return reader
.Value
.ToString()
.Split(_delimiter.ToCharArray())
.ToList();
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
var list = (List<string>)value;
var delimitedList = string.Join(_delimiter, list);
writer.WriteValue(delimitedList);
}
}
Utilizing the overload is as easy as passing it as a second parameter:
public class Foo
{
[JsonConverter(typeof(TagsConverter), " ")]
public List<string> Tags { get; set; }
}
Upvotes: 3