C#JsonConverter JSONArray到字符串w / separator和back

时间:2017-11-17 20:01:54

标签: c# arrays string json.net

我想实现一个自定义JsonConverter来使用,

    [JsonConverter(typeof(ArrayString))]
    public string ServiceCodes { get; set; }

目的是将JSON数组转换为带分隔符的字符串,例如, ["this", "is", "my", "json", "array"]应该成为"this;is;my;json;array"(或任何分隔符)。同样,反过来应该是可能的。

我很难理解覆盖WriteJson的{​​{1}}方法。

为了提供一些上下文,我JsonConverter是实体上的属性(我正在使用EF6)。我认为,除了其他一对多实现之外,做我要求我的案例更容易。然而,我遇到的一个问题是JsonConverter何时被调用?

当getter需要json时,我只希望ServiceCodes给json,即当包含此属性的对象从我的API返回为JSON时。例如,当我编写LINQ时,我不希望调用此转换器。

任何帮助将不胜感激,谢谢。

编辑 - 已添加信息

这是类和一些moc数据。

get

[ComplexType] public class TerminalDuties { public string TerminalCode { get; set; } public string TransportationCode { get; set; } [JsonConverter(typeof(ArrayString))] public string ServiceCodes { get; set; } }

我试过了@ felix-b的答案,但它没有映射。该对象为null。我在ArrayString类中有断点,但它们没有被击中。据推测它没有尝试映射,因为属性是一个字符串。解决方法是什么?

以下是它在我的Web API Controller(从ApiController继承)中公开的方式

"Origin": {
    "TerminalCode": "MIA",
    "TransportationCode": "GT",
    "ServiceCodes": ["WH", "HL"]
}

1 个答案:

答案 0 :(得分:3)

使用.NET Framework 4.6.1,ASP.NET Web API 2,Entity Framework 6.1.3,Newtonsoft.Json 10.0.3进行测试。

<强>更新

我的答案最初需要指定[JsonConverter(typeof(ArrayString), ';')],而不是问题中的[JsonConverter(typeof(ArrayString))]

我在转换器类中添加了默认构造函数,因此分隔符配置是可选的,如果未指定,将使用分号。现在[JsonConverter(typeof(ArrayString))]也可以。

原始回答

只有在通过JSON.NET对您的实体进行序列化和反序列化时才会调用转换器。它不影响从代码获取或设置属性值,也不影响LINQ查询和数据库操作。

这是转换器实现:

public class ArrayString : JsonConverter
{
    private readonly char _delimiter;

    // UPDATE -- added default constructor, so that 
    // JsonConverter attribute can be specified without the 
    // delimiter parameter, in which case semicolon will be used
    public ArrayString() : this(';')
    {
    }

    public ArrayString(char delimiter)
    {
        _delimiter = delimiter;
    }

    public override bool CanRead => true;
    public override bool CanWrite => true;

    public override bool CanConvert(Type objectType)
    {
        return true; 
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType != JsonToken.StartArray)
        {
            return null;
        }

        var stringValue = new StringBuilder();

        while (reader.Read() && reader.TokenType == JsonToken.String)
        {
            if (stringValue.Length > 0)
            {
                stringValue.Append(_delimiter);
            }
            stringValue.Append((string)reader.Value);
        }

        return stringValue.ToString();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var stringValue = value?.ToString();

        if (stringValue == null)
        {
            writer.WriteNull();
            return;
        }

        var arrayValue = stringValue.Split(_delimiter);

        writer.WriteStartArray();

        foreach (var item in arrayValue)
        {
            writer.WriteValue(item);
        }

        writer.WriteEndArray();
    }
}

以下是如何指定分隔符(本例中的分号):

[JsonConverter(typeof(ArrayString), ';')]
public string ServiceCodes { get; set; }