首页 文章

.NET NewtonSoft JSON将映射反序列化为不同的属性名称

提问于
浏览
231

我有以下从外部方收到的JSON字符串 .

{
   "team":[
      {
         "v1":"",
         "attributes":{
            "eighty_min_score":"",
            "home_or_away":"home",
            "score":"22",
            "team_id":"500"
         }
      },
      {
         "v1":"",
         "attributes":{
            "eighty_min_score":"",
            "home_or_away":"away",
            "score":"30",
            "team_id":"600"
         }
      }
   ]
}

我的映射类:

public class Attributes
{
    public string eighty_min_score { get; set; }
    public string home_or_away { get; set; }
    public string score { get; set; }
    public string team_id { get; set; }
}

public class Team
{
    public string v1 { get; set; }
    public Attributes attributes { get; set; }
}

public class RootObject
{
    public List<Team> team { get; set; }
}

问题是我不喜欢Team类中的“Attribute class”和“attributes field name” . 相反,我希望它被命名为“TeamScore”,并从字段名称中删除“_”并给出正确的名称 .

JsonConvert.DeserializeObject<RootObject>(jsonText);

我可以将“属性”类更改为“TeamScore”,但如果我更改了文件名(团队类中的属性),它将不会正确反序列化并使我为空 . 我怎么能克服这个?

4 回答

  • 2

    Json.NETJsonPropertyAttribute ,它允许您指定JSON属性的名称,因此您的代码应为:

    public class TeamScore
    {
        [JsonProperty("eighty_min_score")]
        public string EightyMinScore { get; set; }
        [JsonProperty("home_or_away")]
        public string HomeOrAway { get; set; }
        [JsonProperty("score ")]
        public string Score { get; set; }
        [JsonProperty("team_id")]
        public string TeamId { get; set; }
    }
    
    public class Team
    {
        public string v1 { get; set; }
        [JsonProperty("attributes")]
        public TeamScore TeamScores { get; set; }
    }
    
    public class RootObject
    {
        public List<Team> Team { get; set; }
    }
    

    文件: Serialization Attributes

  • 5

    如果您想使用动态映射,并且不希望使用属性来混淆模型,这种方法对我有用

    用法:

    var settings = new JsonSerializerSettings();
    settings.DateFormatString = "YYYY-MM-DD";
    settings.ContractResolver = new CustomContractResolver();
    this.DataContext = JsonConvert.DeserializeObject<CountResponse>(jsonString, settings);
    

    逻辑:

    public class CustomContractResolver : DefaultContractResolver
    {
        private Dictionary<string, string> PropertyMappings { get; set; }
    
        public CustomContractResolver()
        {
            this.PropertyMappings = new Dictionary<string, string> 
            {
                {"Meta", "meta"},
                {"LastUpdated", "last_updated"},
                {"Disclaimer", "disclaimer"},
                {"License", "license"},
                {"CountResults", "results"},
                {"Term", "term"},
                {"Count", "count"},
            };
        }
    
        protected override string ResolvePropertyName(string propertyName)
        {
            string resolvedName = null;
            var resolved = this.PropertyMappings.TryGetValue(propertyName, out resolvedName);
            return (resolved) ? resolvedName : base.ResolvePropertyName(propertyName);
        }
    }
    
  • 83

    添加到Jacks解决方案 . 我需要使用JsonProperty和Serialize反序列化,同时忽略JsonProperty(反之亦然) . ReflectionHelper和Attribute Helper只是一个辅助类,它获取属性的属性或属性列表 . 我可以包括,如果有人真正关心 . 使用下面的示例,您可以序列化viewmodel并获取“Amount”,即使JsonProperty是“RecurringPrice” .

    /// <summary>
        /// Ignore the Json Property attribute. This is usefule when you want to serialize or deserialize differently and not 
        /// let the JsonProperty control everything.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class IgnoreJsonPropertyResolver<T> : DefaultContractResolver
        {
            private Dictionary<string, string> PropertyMappings { get; set; }
    
            public IgnoreJsonPropertyResolver()
            {
                this.PropertyMappings = new Dictionary<string, string>();
                var properties = ReflectionHelper<T>.GetGetProperties(false)();
                foreach (var propertyInfo in properties)
                {
                    var jsonProperty = AttributeHelper.GetAttribute<JsonPropertyAttribute>(propertyInfo);
                    if (jsonProperty != null)
                    {
                        PropertyMappings.Add(jsonProperty.PropertyName, propertyInfo.Name);
                    }
                }
            }
    
            protected override string ResolvePropertyName(string propertyName)
            {
                string resolvedName = null;
                var resolved = this.PropertyMappings.TryGetValue(propertyName, out resolvedName);
                return (resolved) ? resolvedName : base.ResolvePropertyName(propertyName);
            }
        }
    

    用法:

    var settings = new JsonSerializerSettings();
            settings.DateFormatString = "YYYY-MM-DD";
            settings.ContractResolver = new IgnoreJsonPropertyResolver<PlanViewModel>();
            var model = new PlanViewModel() {Amount = 100};
            var strModel = JsonConvert.SerializeObject(model,settings);
    

    模型:

    public class PlanViewModel
    {
    
        /// <summary>
        ///     The customer is charged an amount over an interval for the subscription.
        /// </summary>
        [JsonProperty(PropertyName = "RecurringPrice")]
        public double Amount { get; set; }
    
        /// <summary>
        ///     Indicates the number of intervals between each billing. If interval=2, the customer would be billed every two
        ///     months or years depending on the value for interval_unit.
        /// </summary>
        public int Interval { get; set; } = 1;
    
        /// <summary>
        ///     Number of free trial days that can be granted when a customer is subscribed to this plan.
        /// </summary>
        public int TrialPeriod { get; set; } = 30;
    
        /// <summary>
        /// This indicates a one-time fee charged upfront while creating a subscription for this plan.
        /// </summary>
        [JsonProperty(PropertyName = "SetupFee")]
        public double SetupAmount { get; set; } = 0;
    
    
        /// <summary>
        /// String representing the type id, usually a lookup value, for the record.
        /// </summary>
        [JsonProperty(PropertyName = "TypeId")]
        public string Type { get; set; }
    
        /// <summary>
        /// Billing Frequency
        /// </summary>
        [JsonProperty(PropertyName = "BillingFrequency")]
        public string Period { get; set; }
    
    
        /// <summary>
        /// String representing the type id, usually a lookup value, for the record.
        /// </summary>
        [JsonProperty(PropertyName = "PlanUseType")]
        public string Purpose { get; set; }
    }
    
  • 467

    扩展Rentering.com's答案,在需要处理多种类型的完整图表的情况下,并且您正在寻找强类型解决方案,此类可以提供帮助,请参阅下面的用法(流畅) . 它可以作为黑名单或每种类型的白名单运行 . 类型不能同时存在(Gist - 也包含全局忽略列表) .

    public class PropertyFilterResolver : DefaultContractResolver
    {
      const string _Err = "A type can be either in the include list or the ignore list.";
      Dictionary<Type, IEnumerable<string>> _IgnorePropertiesMap = new Dictionary<Type, IEnumerable<string>>();
      Dictionary<Type, IEnumerable<string>> _IncludePropertiesMap = new Dictionary<Type, IEnumerable<string>>();
      public PropertyFilterResolver SetIgnoredProperties<T>(params Expression<Func<T, object>>[] 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<T>(params Expression<Func<T, object>>[] 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<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
      {
        var properties = base.CreateProperties(type, memberSerialization);
    
        var isIgnoreList = _IgnorePropertiesMap.TryGetValue(type, out IEnumerable<string> map);
        if (!isIgnoreList && !_IncludePropertiesMap.TryGetValue(type, out map))
          return properties;
    
        Func<JsonProperty, bool> predicate = jp => map.Contains(jp.PropertyName) == !isIgnoreList;
        return properties.Where(predicate).ToArray();
      }
    
      string GetPropertyName<TSource, TProperty>(
      Expression<Func<TSource, TProperty>> 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;
      }
    }
    

    用法:

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

相关问题