/ / .NET NewtonSoft JSON désérialise la carte avec un nom de propriété différent - json, c # -4.0, sérialisation, désérialisation, json.net

.NET NewtonSoft JSON désérialise la carte avec un nom de propriété différent - json, c # -4.0, sérialisation, désérialisation, json.net

J'ai la chaîne JSON suivante qui est reçue d'une partie externe.

{
"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"
}
}
]
}

Mes cours de cartographie:

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; }
}

La question est que je n'aime pas l'attributclass "et le" Attribute field name "dans la classe Team. Au lieu de cela, je veux qu'il soit nommé" TeamScore "et aussi pour supprimer" _ "des noms de champ et donner des noms propres.

JsonConvert.DeserializeObject<RootObject>(jsonText);

Je peux changer la classe "Attribute" en "TeamScore", mais si je change le nom déposé (attributs dans la classe Team), il ne se désérialisera pas correctement et me donnera la valeur null. Comment puis-je surmonter cela?

Réponses:

450 pour la réponse № 1

Json.NET a un JsonPropertyAttribute qui vous permet de spécifier le nom d'une propriété JSON, donc votre code doit être:

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; }
}

Documentation: Attributs de sérialisation


74 pour la réponse № 2

Si vous souhaitez utiliser le mappage dynamique et que vous ne voulez pas encombrer votre modèle avec des attributs, cette approche a fonctionné pour moi

Usage:

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

Logique:

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);
}
}

3 pour la réponse № 3

Ajout à la solution Jacks. J'ai besoin de désérialiser en utilisant JsonProperty et Serialize tout en ignorant JsonProperty (ou vice versa). ReflectionHelper et Attribute Helper ne sont que des classes d'assistance qui obtiennent une liste de propriétés ou d'attributs pour une propriété. Je peux inclure si quelqu'un s'en soucie réellement. En utilisant l'exemple ci-dessous, vous pouvez sérialiser le viewmodel et obtenir "Amount" même si le JsonProperty est "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);
}
}

Usage:

        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);

Modèle:

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; }
}

1 pour la réponse № 4

Expansion Rentering.com "s répondre, dans des scénarios où un graphique entier de nombreuxtypes doit être pris en charge, et vous êtes à la recherche d'une solution fortement typée, cette classe peut vous aider, voir l'utilisation (couramment) ci-dessous. Elle fonctionne comme une liste noire ou une liste blanche par type. Un type ne peut pas être tous les deux (Essentiel - contient également une liste d'ignorance globale).

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;
}
}

Usage:

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