C# 为json.net编写可重用的JSONConverter

C# 为json.net编写可重用的JSONConverter,c#,.net,json.net,C#,.net,Json.net,我正在查询一个以多种格式返回标记列表的服务: { "tags": "a,b,c" } 或 或 我想将其反序列化到的对象是列表。我编写了一个tagscoverter,它实现了JsonConverter中的必要方法,如下所示: public class TagsConverter : JsonConverter { public override bool CanConvert(Type objectType) { return (objectType == t

我正在查询一个以多种格式返回标记列表的服务:

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

我想将其反序列化到的对象是
列表
。我编写了一个
tagscoverter
,它实现了
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);
    }
}
公共类标记转换程序:JsonConverter
{
公共覆盖布尔CanConvert(类型objectType)
{
返回(objectType==typeof(string));
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
回传读取器
价值
.ToString()
.拆分(“”)
.ToList();
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
var list=(list)值;
var delimitedList=string.Join(“,list);
writer.WriteValue(delimitedList);
}
}
然后我在对象中注释字段,如下所示:

public class Foo
{
  [JsonConverter(typeof(TagsConverter))]
  public List<string> Tags { get; set; }
}
公共类Foo
{
[JsonConverter(类型(标记转换器))]
公共列表标记{get;set;}
}
这是可行的,但只适用于由空格分隔的标记

但是,如果我能够以参数化方式更改
Split
Join
函数,则
tagscoverter
可以在所有3种情况下工作。但是,由于我们只将类型传递给
JsonConverter
属性,因此我理解这里不能将“分隔符”作为参数传递


有什么方法可以实现这一点吗?

还有一个额外的
JsonConverter
,它同时接受一个类型和一个
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);
    }
}
公共类标记转换程序:JsonConverter
{
专用只读字符串_分隔符;
公共标记转换器(字符串分隔符)
{
_分隔符=分隔符;
}
公共覆盖布尔CanConvert(类型objectType)
{
返回(objectType==typeof(string));
}
公共重写对象ReadJson(JsonReader reader,类型objectType,
对象存在值,JsonSerializer序列化程序)
{
回传读取器
价值
.ToString()
.Split(_delimiter.ToCharArray())
.ToList();
}
公共重写void WriteJson(JsonWriter writer,对象值,
JsonSerializer(序列化程序)
{
var list=(list)值;
var delimitedList=string.Join(_delimiter,list);
writer.WriteValue(delimitedList);
}
}
使用重载与将其作为第二个参数传递一样简单:

public class Foo
{
    [JsonConverter(typeof(TagsConverter), " ")]
    public List<string> Tags { get; set; }
}
公共类Foo
{
[JsonConverter(类型(标记转换器),“”)
公共列表标记{get;set;}
}

如果只需要读取/反序列化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();
}

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

我喜欢这个解决方案,但是你不需要两个创建三个独立的
Foo
类,每个类都有一个定界符吗?@marainesparnisari根据提供的代码,你怎么会认为这不是OP想要的呢?据我所知,OP需要一个可重用的转换器,可以应用于多个类,每个类使用不同的分隔符,这正是我所提供的。也就是说,如果你对这个问题有另一种解释的话,我很想听听:)。不,不,我想这正是OP想要的。我只是在想,是否有一种替代方法可以涉及在
Foo
中使用泛型。@marainesparnisari泛型只会给您提供编译时类型差异…而不是编译时或运行时参数差异,这就是OP后面的内容。我怀疑仿制药会增加任何价值。请记住,属性参数必须是编译时常量,因此任何类型的变量输入都不会编译。其目的是在不同的类中使用相同的转换器,如David假设。感谢您提供此解决方案,我甚至不知道它的存在:)这也很棒。但我发现David()提出的解决方案更符合我的意愿。谢谢你的回答:)
public class Foo
{
    [JsonConverter(typeof(TagsConverter), " ")]
    public List<string> Tags { get; set; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    return reader
            .Value
            .ToString()
            .Split(new char[]{' ', ',', '+'}, StringSplitOptions.RemoveEmptyEntries)
            .ToList();
}