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

Posted

技术标签:

【中文标题】如何将自定义属性转换为 Json 字符串【英文标题】:How to Convert Custom Attribute into Json String 【发布时间】:2015-05-18 06:45:11 【问题描述】:

当我调用 JsonConvert.SerializeObject(...) 函数时,有什么方法可以将我的任何自定义属性转换为某种东西?比如我有一个类:

class A

  [UnitAttribute("---")]
  public double? Ratio  get; set;  

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

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

【问题讨论】:

【参考方案1】:

最简单的做法是创建一个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,该IContractResolver 派生自现有的合约解析器,例如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中自动使用。

【讨论】:

以上是关于如何将自定义属性转换为 Json 字符串的主要内容,如果未能解决你的问题,请参考以下文章

将自定义javascript对象转换为json [重复]

无法将自定义数据类型转换为字符串?

如何将自定义 json 转换为自适应卡片 json 格式

Swift 4 如何将自定义对象数组转换为 JSON

将自定义 JsonConverter 添加到 Web API 会影响传递给自定义验证属性的字符串值

如何将自定义视图拖动为 Xcode 6 中自定义视图的私有属性