.Чистая NewtonSoft JSON и десериализовать карту на другое имя недвижимость
у меня есть следующая строка 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. Вместо этого я хочу, чтобы он был назван "TeamScore", а также удалить "_" из имен полей и дать имена собственные.
JsonConvert.DeserializeObject<RootObject>(jsonText);
Я могу изменить класс "атрибут" на "TeamScore", но если я изменю имя файла (атрибуты в классе Team), он не десериализуется должным образом и дает мне null. Как я могу преодолеть это?
4 ответа:
Json.NET имеет
JsonPropertyAttribute
что позволяет указать имя свойства 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; } }
документы: Сериализации Атрибутов
Если вы хотите использовать динамическое отображение и не хотите загромождать свою модель атрибутами, этот подход сработал для меня
использование:
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); } }
добавление к решению гнезд. Мне нужно десериализовать с помощью JsonProperty и сериализовать, игнорируя JsonProperty (или наоборот). ReflectionHelper и Attribute Helper - это просто вспомогательные классы, которые получают список свойств или атрибутов для свойства. Я могу включить если кто-то действительно заботится. Используя приведенный ниже пример, вы можете сериализовать viewmodel и получить "сумму", даже если 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; } }
расширение Rentering.com ' S Ответ, в сценариях, где необходимо позаботиться о целом графике многих типов, и вы ищете строго типизированное решение, этот класс может помочь, см. Использование (fluent) ниже. Он работает как черный список или белый список для каждого типа. Тип не может быть обоими (суть - также содержит глобальный список игнорирования).
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