为json.net编写可重用的JsonConverters

时间:2017-06-04 02:55:55

标签: c# .net json.net

我正在查询以多种格式返回标签​​列表的服务:

{
  "tags": "a,b,c"
}

{
  "tags": "a b c"
}

{
  "tags": "a+b+c"
}

我要将其反序列化的对象是List<string>。我已经编写了一个TagsConverter来实现JsonConverter中必要的方法,如下所示:

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

然后我像这样注释对象中的字段:

public class Foo
{
  [JsonConverter(typeof(TagsConverter))]
  public List<string> Tags { get; set; }
}

这样可行,但仅适用于以空格分隔的标签。

但是,如果我能够以参数化方式更改TagsConverterSplit函数,Join可以在所有3种情况下都有效。但由于我们只将类型传递给JsonConverter属性,因此我知道我们无法通过&#34;分隔符&#34;作为一个论点。

有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:3)

还有一个额外的JsonConverter constructor overload同时将 类型params object[] converterParameters注入到具体实例中你的转换器。您可以利用此过载来最大化您的可重用性。

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

利用过载就像传递第二个参数一样简单:

public class Foo
{
    [JsonConverter(typeof(TagsConverter), " ")]
    public List<string> Tags { get; set; }
}

答案 1 :(得分:2)

如果只需要JSON的读取/反序列化,请注意string.Split可以采用字符数组char[]

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    return reader
            .Value
            .ToString()
            .Split(new char[]{' ', ',', '+'}, StringSplitOptions.RemoveEmptyEntries)
            .ToList();
}

这意味着转换器在读取时可以处理所有三个分隔符。