对属性执行Json DeserializeObject转换

3
假设有以下json字符串:
```json ``` 请注意,保留HTML标记。
string json = '{"string_property":"foo_bar", ... other objects here ...}';

我想知道是否有一种方法可以对解析出的对象运行转换,以便在运行以下方法后,不再获取foo_bar,而是获取foo bar(可以是任何方法)。

public string Transform(string s) {
    return s.Replace("_"," ");
}

我可以在反序列化后手动更改我的poco,但想知道是否有更“清晰”的方法?


1
请查看http://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm。 - Callum Linington
你是想转换属性名称还是只转换值?并且你希望所有属性都采用相同的转换吗? - Eric Linde
除非您需要更改属性名称并且希望所有字符串属性使用相同的转换,否则最清晰的方法是首先进行反序列化,然后使用反射转换所有字符串属性的值。 - Eric Linde
@EricLinde 不,我很满意将所有名称保留原样,我正试图从字符串中清除一些HTML标签。我猜我可以在所有字符串上运行该方法,尽管我知道它只适用于30-40个对象中的2个数组。 - Noctis
2个回答

5

在反序列化根对象时,您可以使用针对所有字符串类型值的自定义Json转换器,将您的string属性转换为所需格式:

public class ReplacingStringConverter : JsonConverter
{
    readonly string oldValue;
    readonly string newValue;

    public ReplacingStringConverter(string oldValue, string newValue)
    {
        if (string.IsNullOrEmpty(oldValue))
            throw new ArgumentException("string.IsNullOrEmpty(oldValue)");
        if (newValue == null)
            throw new ArgumentNullException("newValue");
        this.oldValue = oldValue;
        this.newValue = newValue;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var s = (string)JToken.Load(reader);
        return s.Replace(oldValue, newValue);
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后像这样使用它:
var settings = new JsonSerializerSettings { Converters = new[] { new ReplacingStringConverter("_", "") } };
var result = JsonConvert.DeserializeObject<RootObject>(json, settings);

请注意,如果单个字符串类型属性直接应用了自己的转换器,可以使用 [JsonConverter(Type)] ,那么将优先使用这些转换器,而不是在 Converters 列表中的 ReplacingStringConverter

谢谢你的指引,让我找到了正确的方向。这是我的解决方案。我曾考虑过删除属性并处理“缺失”的属性,但对于我的需求来说太麻烦了。 - Noctis

2
我将做以下事情:
首先,创建一个仅读取并进行URL解码的字符串转换器。
public class UrlDecoderConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var s = (string)JToken.Load(reader);
        return HttpUtility.UrlDecode(s);
    }

    public override bool CanWrite => false;

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后,只需将以下内容添加到需要解码的 POCO 属性中:
[JsonConverter(typeof(UrlDecoderConverter))]
public string url { get; set; }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接