Xamarin C#中如何读取包含多类型数据的JSON?
问题:Xamarin C#解析含数组的JSON数据失败
在Xamarin C#中向数据库请求数据,返回字典列表形式的JSON,但现有代码仅能处理string类型数据,无法解析数组等复杂类型,执行时报错。
原代码
if (response.IsSuccessStatusCode) { string json = await response.Content.ReadAsStringAsync(); Dictionary<string, List<Dictionary<string, string>>> reponse = JsonConvert.DeserializeObject<Dictionary<string, List<Dictionary<string, string>>>>(json); List<Dictionary<string, string>> resultat = reponse["reponse"]; foreach (Dictionary<string, string> dicoProfil in resultat) { //Initialisation des variables string nomProfilAAjouter = dicoProfil["Usager"]; string nomPropriete = dicoProfil["Predicat"]; string valeurPropriete = dicoProfil["Caracteristique"]; string dataProperty = dicoProfil["Dataproperty"]; string valeurdata = dicoProfil["Valeurdata"]; //Modification du profil si un profil avec le même nom existe déjà if ("profil:"+nomProfil==nomProfilAAjouter) { if (profils.ContainsKey(nomProfilAAjouter)) { await SetProperty(nomPropriete, valeurPropriete, dataProperty, valeurdata, profils[nomProfilAAjouter]); } //Ajout du profil else { Profil newProfil = new Profil(); await SetProperty(nomPropriete, valeurPropriete, dataProperty, valeurdata, newProfil); profils[nomProfilAAjouter] = newProfil; } } } } return profils["profil:" + nomProfil] ; }
待解析的JSON结构
[ { "Usager": "profil:Jean_PIERRE", "rdf:type": "owl:NamedIndividual", "profil:A_Pour_Comportement": "profil:9e7b483e_cec8_4ce7_8ae2_6e693859a043", "profil:A_Pour_Droit": "profil:Administrateur", "profil:A_Pour_Espace_Travail": "arch:IfcSpace_12783", "profil:A_Pour_Habitude": "profil:7228afa0_ce7b_4b76_a640_6e2ec2cbcb23", "profil:A_Pour_Profession": "profil:Responsable_informatique", "schema:givenName": "Jean", "schema:name": "PIERRE", "profil:A_Pour_Competence": [ {"caracteristique": "profil:Cuisine", "valeurdata": "4", "predicat": "profil:Niveau_expertise"}, {"caracteristique": "profil:Réseau", "valeurdata": "7", "predicat": "profil:Niveau_expertise"} ], "profil:A_Pour_Modèle_Usager": [ {"caracteristique": "modele:ac63f979_aa26_4bf5_a308_b1d30bd9cbae", "valeurdata": "Modèle_Lum_Jean", "predicat": "modele:Description"}, {"caracteristique": "modele:ac63f979_aa26_4bf5_a308_b1d30bd9cbae", "valeurdata": "Modèle Lumiere Jean", "predicat": "modele:Nom"}, {"caracteristique": "modele:f95314a6_ffc8_4481_95a6_0ed2db5e4854", "valeurdata": "Modèle_Temp_Jean", "predicat": "modele:Description"}, {"caracteristique": "modele:f95314a6_ffc8_4481_95a6_0ed2db5e4854", "valeurdata": "Modèle Temperature Jean", "predicat": "modele:Nom"} ] } ]
错误信息
An error occurred: 'Unexpected character encountered while parsing value: [. Path 'reponse[0].profil:A_Pour_Competence', line 1, position 545.'. Callstack: ' at Newtonsoft.Json.JsonTextReader.ReadStringValue (Newtonsoft.Json.ReadType readType)
解决方案
方法1:使用JToken/JObject动态解析(快速适配复杂结构)
将强类型字典替换为Newtonsoft.Json的JObject/JToken类型,自动适配JSON中的字符串、数组、对象等所有类型:
if (response.IsSuccessStatusCode) { string json = await response.Content.ReadAsStringAsync(); // JSON根节点是数组,先反序列化为JArray JArray resultat = JsonConvert.DeserializeObject<JArray>(json); foreach (JObject dicoProfil in resultat) { string nomProfilAAjouter = dicoProfil["Usager"].Value<string>(); if ("profil:" + nomProfil == nomProfilAAjouter) { Profil targetProfil; // 查找或创建目标Profil实例 if (!profils.TryGetValue(nomProfilAAjouter, out targetProfil)) { targetProfil = new Profil(); profils[nomProfilAAjouter] = targetProfil; } // 遍历所有属性,区分类型处理 foreach (var property in dicoProfil.Properties()) { string propName = property.Name; JToken propValue = property.Value; // 处理字符串类型字段 if (propValue.Type == JTokenType.String) { await SetProperty(propName, propValue.Value<string>(), null, null, targetProfil); } // 处理数组类型字段 else if (propValue.Type == JTokenType.Array) { foreach (JObject item in propValue.Children<JObject>()) { string predicat = item["predicat"].Value<string>(); string caracteristique = item["caracteristique"].Value<string>(); string valeurdata = item["valeurdata"].Value<string>(); await SetProperty(predicat, caracteristique, null, valeurdata, targetProfil); } } } } } } return profils["profil:" + nomProfil];
方法2:创建匹配JSON结构的实体类(强类型,类型安全)
根据JSON结构定义对应的C#实体类,让Newtonsoft.Json自动完成类型映射:
// 根节点数组的条目类 public class ProfilEntry { [JsonProperty("Usager")] public string Usager { get; set; } [JsonProperty("rdf:type")] public string RdfType { get; set; } [JsonProperty("profil:A_Pour_Comportement")] public string APourComportement { get; set; } [JsonProperty("profil:A_Pour_Droit")] public string APourDroit { get; set; } [JsonProperty("profil:A_Pour_Espace_Travail")] public string APourEspaceTravail { get; set; } [JsonProperty("profil:A_Pour_Habitude")] public string APourHabitude { get; set; } [JsonProperty("profil:A_Pour_Profession")] public string APourProfession { get; set; } [JsonProperty("schema:givenName")] public string GivenName { get; set; } [JsonProperty("schema:name")] public string Name { get; set; } [JsonProperty("profil:A_Pour_Competence")] public List<CompetenceItem> APourCompetence { get; set; } [JsonProperty("profil:A_Pour_Modèle_Usager")] public List<ModeleUsagerItem> APourModeleUsager { get; set; } } // Competence数组的条目类 public class CompetenceItem { [JsonProperty("caracteristique")] public string Caracteristique { get; set; } [JsonProperty("valeurdata")] public string Valeurdata { get; set; } [JsonProperty("predicat")] public string Predicat { get; set; } } // Modèle Usager数组的条目类 public class ModeleUsagerItem { [JsonProperty("caracteristique")] public string Caracteristique { get; set; } [JsonProperty("valeurdata")] public string Valeurdata { get; set; } [JsonProperty("predicat")] public string Predicat { get; set; } }
修改解析代码:
if (response.IsSuccessStatusCode) { string json = await response.Content.ReadAsStringAsync(); List<ProfilEntry> resultat = JsonConvert.DeserializeObject<List<ProfilEntry>>(json); foreach (ProfilEntry entry in resultat) { if ("profil:" + nomProfil == entry.Usager) { Profil targetProfil; if (!profils.TryGetValue(entry.Usager, out targetProfil)) { targetProfil = new Profil(); profils[entry.Usager] = targetProfil; } // 处理普通字符串属性 await SetProperty("rdf:type", entry.RdfType, null, null, targetProfil); await SetProperty("profil:A_Pour_Comportement", entry.APourComportement, null, null, targetProfil); // 其他普通属性同理补充 // 处理Competence数组 foreach (var comp in entry.APourCompetence) { await SetProperty(comp.Predicat, comp.Caracteristique, null, comp.Valeurdata, targetProfil); } // 处理Modèle Usager数组 foreach (var modele in entry.APourModeleUsager) { await SetProperty(modele.Predicat, modele.Caracteristique, null, modele.Valeurdata, targetProfil); } } } } return profils["profil:" + nomProfil];
关键说明
- 原代码报错核心原因:强制将所有JSON值解析为
string,但JSON中存在数组类型,解析器无法完成类型转换。 - 方法1适合动态/复杂JSON场景,灵活性高;方法2适合结构固定的场景,类型安全、可读性更强。
内容的提问来源于stack exchange,提问作者Antoine21000
相关产品推荐
相关产品推荐

