.NET NewtonSoft JSON deserialize map to a different property name

后端 未结 5 777
情歌与酒
情歌与酒 2020-11-22 09:20

I have following JSON string which is received from an external party.

{
   \"team\":[
      {
         \"v1\":\"\",
         \"attributes\":{
            \"         


        
5条回答
  •  Happy的楠姐
    2020-11-22 09:36

    Expanding Rentering.com's answer, in scenarios where a whole graph of many types is to be taken care of, and you're looking for a strongly typed solution, this class can help, see usage (fluent) below. It operates as either a black-list or white-list per type. A type cannot be both (Gist - also contains global ignore list).

    public class PropertyFilterResolver : DefaultContractResolver
    {
      const string _Err = "A type can be either in the include list or the ignore list.";
      Dictionary> _IgnorePropertiesMap = new Dictionary>();
      Dictionary> _IncludePropertiesMap = new Dictionary>();
      public PropertyFilterResolver SetIgnoredProperties(params Expression>[] propertyAccessors)
      {
        if (propertyAccessors == null) return this;
    
        if (_IncludePropertiesMap.ContainsKey(typeof(T))) throw new ArgumentException(_Err);
    
        var properties = propertyAccessors.Select(GetPropertyName);
        _IgnorePropertiesMap[typeof(T)] = properties.ToArray();
        return this;
      }
    
      public PropertyFilterResolver SetIncludedProperties(params Expression>[] propertyAccessors)
      {
        if (propertyAccessors == null)
          return this;
    
        if (_IgnorePropertiesMap.ContainsKey(typeof(T))) throw new ArgumentException(_Err);
    
        var properties = propertyAccessors.Select(GetPropertyName);
        _IncludePropertiesMap[typeof(T)] = properties.ToArray();
        return this;
      }
    
      protected override IList CreateProperties(Type type, MemberSerialization memberSerialization)
      {
        var properties = base.CreateProperties(type, memberSerialization);
    
        var isIgnoreList = _IgnorePropertiesMap.TryGetValue(type, out IEnumerable map);
        if (!isIgnoreList && !_IncludePropertiesMap.TryGetValue(type, out map))
          return properties;
    
        Func predicate = jp => map.Contains(jp.PropertyName) == !isIgnoreList;
        return properties.Where(predicate).ToArray();
      }
    
      string GetPropertyName(
      Expression> propertyLambda)
      {
        if (!(propertyLambda.Body is MemberExpression member))
          throw new ArgumentException($"Expression '{propertyLambda}' refers to a method, not a property.");
    
        if (!(member.Member is PropertyInfo propInfo))
          throw new ArgumentException($"Expression '{propertyLambda}' refers to a field, not a property.");
    
        var type = typeof(TSource);
        if (!type.GetTypeInfo().IsAssignableFrom(propInfo.DeclaringType.GetTypeInfo()))
          throw new ArgumentException($"Expresion '{propertyLambda}' refers to a property that is not from type '{type}'.");
    
        return propInfo.Name;
      }
    }
    

    Usage:

    var resolver = new PropertyFilterResolver()
      .SetIncludedProperties(
        u => u.Id, 
        u => u.UnitId)
      .SetIgnoredProperties(
        r => r.Responders)
      .SetIncludedProperties(
        b => b.Id)
      .Ignore(nameof(IChangeTracking.IsChanged)); //see gist
    

提交回复
热议问题