private static T Populate <T>(Newtonsoft.Json.Linq.JToken jsonToken, T target, JsonSerializer serializer) { // Si on exploite "target" sous sa forme typée alors le SetValue n'impacte pas l'instance de notre objet object targetObject = (object)target; Type targetType = target.GetType(); Dictionary <List <string>, MemberInfo> lstMembers = new Dictionary <List <string>, MemberInfo>(); List <MemberInfo> memberInfosAtCheck = new List <MemberInfo>(); memberInfosAtCheck.AddRange(targetType.GetProperties()); memberInfosAtCheck.AddRange(targetType.GetFields()); foreach (MemberInfo memberInfo in memberInfosAtCheck) { JsonPropertyAttribute propAtt = null; JsonConverterAttribute convAtt = null; JsonPathAttribute pathAtt = null; List <string> jsonPaths = null; ToolsJsonNet.GetJsonAttributeAndPathsByMemberInfo(memberInfo, out propAtt, out pathAtt, out convAtt, out jsonPaths); #region Application du Converter JsonConverter conv = null; if (serializer != null && convAtt != null) { conv = (JsonConverter)Activator.CreateInstance(convAtt.ConverterType); serializer.Converters.Add(conv); } #endregion lstMembers.Add(jsonPaths, memberInfo); } foreach (List <string> memberPaths in lstMembers.Keys) { JToken jToken = null; foreach (string memberPath in memberPaths) { IEnumerator <JToken> jTokens = jsonToken.SelectTokens(memberPath).GetEnumerator(); // Récupération du 1er element de la liste (si existant) if (jTokens.MoveNext()) { jToken = jTokens.Current; } // On exploite le 1er path qui match avec notre Json if (jToken != null) { break; } } if (jToken != null && jToken.Type != JTokenType.Null) { if (lstMembers[memberPaths] is PropertyInfo) { PropertyInfo propertyInfo = (PropertyInfo)lstMembers[memberPaths]; object value = ExtractValue(serializer, jToken, propertyInfo.PropertyType); propertyInfo.SetValue(targetObject, value, null); } else { FieldInfo fieldInfo = (FieldInfo)lstMembers[memberPaths]; object value = ExtractValue(serializer, jToken, fieldInfo.FieldType); fieldInfo.SetValue(targetObject, value); } } } return((T)targetObject); }
/// <summary> /// Méthode de lecture du Json /// </summary> /// <param name="reader"></param> /// <param name="objectType"></param> /// <param name="existingValue"></param> /// <param name="serializer"></param> /// <returns></returns> public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject jo = JObject.Load(reader); object targetObj = Activator.CreateInstance(objectType); foreach (PropertyInfo prop in objectType.GetProperties()) { if (prop.CanRead && prop.CanWrite) { JsonPropertyAttribute propAtt = null; JsonPathAttribute pathAtt = null; JsonConverterAttribute convAtt = null; List <string> jsonPaths = null; ToolsJsonNet.GetJsonAttributeAndPathsByMemberInfo(prop, out propAtt, out pathAtt, out convAtt, out jsonPaths); #region Application du Converter JsonConverter conv = null; if (serializer != null && convAtt != null) { conv = (JsonConverter)Activator.CreateInstance(convAtt.ConverterType); serializer.Converters.Add(conv); } #endregion JToken token = null; foreach (string jsonPath in jsonPaths) { token = jo.SelectToken(jsonPath); // On exploite le 1er path qui match avec notre Json if (token != null) { break; } } if (token != null && token.Type != JTokenType.Null) { // Si le token est un noeud final de l'arbre, qu'il n'est pas une chaîne de caractére et que le noeud Json ne posséde pas de valeur if (token is JValue && prop.PropertyType != typeof(string) && ((JValue)token).Value is string && ((string)((JValue)token).Value) == string.Empty) { // On assigne la valeur par default du Type (cela évite des probléme de cast avec les int et autre type) prop.SetValue(targetObj, ToolsType.GetDefault(prop.PropertyType), null); } else { object value = token.ToObject(prop.PropertyType, serializer); prop.SetValue(targetObj, value, null); } } } } foreach (FieldInfo field in objectType.GetFields()) { JsonPropertyAttribute propAtt = null; JsonPathAttribute pathAtt = null; JsonConverterAttribute convAtt = null; List <string> jsonPaths = null; ToolsJsonNet.GetJsonAttributeAndPathsByMemberInfo(field, out propAtt, out pathAtt, out convAtt, out jsonPaths); #region Application du Converter JsonConverter conv = null; if (serializer != null && convAtt != null) { conv = (JsonConverter)Activator.CreateInstance(convAtt.ConverterType); serializer.Converters.Add(conv); } #endregion JToken token = null; foreach (string jsonPath in jsonPaths) { token = jo.SelectToken(jsonPath); // On exploite le 1er path qui match avec notre Json if (token != null) { break; } } if (token != null && token.Type != JTokenType.Null) { // Si le token est un noeud final de l'arbre, qu'il n'est pas une chaîne de caractére et que le noeud Json ne posséde pas de valeur if (token is JValue && field.FieldType != typeof(string) && ((JValue)token).Value is string && ((string)((JValue)token).Value) == string.Empty) { // On assigne la valeur par default du Type (cela évite des probléme de cast avec les int et autre type) field.SetValue(targetObj, ToolsType.GetDefault(field.FieldType)); } else { object value = token.ToObject(field.FieldType, serializer); field.SetValue(targetObj, value); } } } return(targetObj); }
internal static void GetJsonAttributeAndPathsByMemberInfo(MemberInfo memberInfo, out JsonPropertyAttribute propAtt, out JsonPathAttribute pathAtt, out JsonConverterAttribute convAtt, out List <string> jsonPaths) { propAtt = null; pathAtt = null; convAtt = null; jsonPaths = new List <string>(); foreach (object customAttribute in memberInfo.GetCustomAttributes(true)) { if (customAttribute.GetType() == typeof(JsonPropertyAttribute)) { propAtt = customAttribute as JsonPropertyAttribute; } else if (customAttribute.GetType() == typeof(JsonPathAttribute)) { pathAtt = customAttribute as JsonPathAttribute; } else if (customAttribute.GetType() == typeof(JsonConverterAttribute)) { convAtt = customAttribute as JsonConverterAttribute; } } #region Récupération des Path par priorité : JsonPath / JsonProperty / PropertyName if (propAtt != null && !String.IsNullOrEmpty(propAtt.PropertyName)) { jsonPaths.Add(propAtt.PropertyName); } if (pathAtt != null) { foreach (string path in pathAtt.JPaths) { jsonPaths.Add(path); } } jsonPaths.Add(memberInfo.Name); #endregion }