如何将自定义属性转换为Json字符串

时间:2015-05-18 06:45:11

标签: json.net

当我调用JsonConvert.SerializeObject(...)函数时,有没有办法将我的任何自定义属性转换为某些东西?例如,我有一个班级:

class A
{
  [UnitAttribute("---")]
  public double? Ratio { get; set; } 
}

序列化此类的任何实例时,有没有办法将UnitAttribute的值放入Json字符串?

我发现API中有一个IAttributeProvider接口。但似乎序列化函数并没有真正使用它。

1 个答案:

答案 0 :(得分:0)

最简单的方法是创建一个JsonConverter来添加属性文本(我假设它对应于单位,在这种情况下)并将转换器附加到属性:

class A
{
    [JsonConverter(typeof(UnitConverter), new object [] { "mm" })]
    public double? Ratio { get; set; }
}

public class UnitConverter : JsonConverter
{
    public string Units { get; set; }

    string UnitsPostfix { get { return string.IsNullOrEmpty(Units) ? string.Empty : " " + Units; } }

    public UnitConverter(string units)
    {
        this.Units = units;
    }

    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException(); // Not called when applied directly to a property.
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jvalue = JValue.Load(reader);
        if (jvalue.Type == JTokenType.String)
        {
            var s = (string)jvalue;
            if (s.EndsWith(Units))
                jvalue = (JValue)s.Substring(0, s.LastIndexOf(Units)).Trim();
        }
        return jvalue.ToObject(objectType);

    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var jvalue = JValue.FromObject(value);
        if (jvalue.Type == JTokenType.Null)
            jvalue.WriteTo(writer);
        else
            writer.WriteValue((string)jvalue + UnitsPostfix);
    }
}

注意我可以将单位字符串直接传递给属性声明中的转换器构造函数。

如果您的代码库中有许多字段和属性UnitAttribute,并希望自动将转换器应用于所有字段和属性,则可以创建从现有合同解析程序派生的自定义IContractResolver as DefaultContractResolver应用必要的转换器:

public class UnitContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        if (property.Converter == null && property.MemberConverter == null)
        {
            var attr = property.AttributeProvider.GetAttributes(typeof(UnitAttribute), true).Cast<UnitAttribute>().Where(a => !string.IsNullOrEmpty(a.Name)).FirstOrDefault();
            if (attr != null)
            {
                property.Converter = property.MemberConverter = new UnitConverter(attr.Name);
            }
        }
        return property;
    }
}

您可以明确使用合约解析程序,如下所示:

        var settings = new JsonSerializerSettings() { ContractResolver = new UnitContractResolver() };

        var json = JsonConvert.SerializeObject(a, settings);
        Debug.WriteLine(json);
        var a11 = JsonConvert.DeserializeObject<A>(json, settings);
        Debug.Assert(a.Ratio == a.Ratio);

或者在Json.net global settings中将其设置为自动使用。