Json deserialization c# avec non conforme json
Résolu/Fermé
ryko1820
Messages postés
1677
Date d'inscription
dimanche 28 avril 2013
Statut
Membre
Dernière intervention
15 août 2021
-
Modifié par ryko1820 le 13/03/2016 à 16:27
Utilisateur anonyme - 14 mars 2016 à 17:59
Utilisateur anonyme - 14 mars 2016 à 17:59
4 réponses
Utilisateur anonyme
13 mars 2016 à 16:31
13 mars 2016 à 16:31
Bonjour,
le json je ne connais pas (enfin si, mais je n'ai jamais travaillé dessus), par contre pour sortir 3 lignes, tu peux passer par un fichier temporaire:
Sinon, peut être peux tu envisager d'écrire ton propre parseur.
le json je ne connais pas (enfin si, mais je n'ai jamais travaillé dessus), par contre pour sortir 3 lignes, tu peux passer par un fichier temporaire:
File.WriteAllLines("temp.json", File.ReadLines(@".\\config.json").Skip(3));
Sinon, peut être peux tu envisager d'écrire ton propre parseur.
Utilisateur anonyme
13 mars 2016 à 18:04
13 mars 2016 à 18:04
Si j'ai bien compris dans
tu veux virer
Est ce que la séquence
peut se répéter plusieurs fois?
{
"foo" : "1",
"bar" : "1"
}{
"titi" : "val1",
"toto" : "val2",
"tutu" : "val3"
}
tu veux virer
{
"foo" : "1",
"bar" : "1"
}
Est ce que la séquence
{
"titi" : "val1",
"toto" : "val2",
"tutu" : "val3"
}
peut se répéter plusieurs fois?
ryko1820
Messages postés
1677
Date d'inscription
dimanche 28 avril 2013
Statut
Membre
Dernière intervention
15 août 2021
276
Modifié par ryko1820 le 13/03/2016 à 19:13
Modifié par ryko1820 le 13/03/2016 à 19:13
En fait le plus simple pour que le JSON soit conforme, consisterait dans l'effacement de ...
... de mon stream parsé. Tout le reste passe les validateurs JSON quand cette espèce d' "entête" est effacée, et pourtant le fichier fait des centaines de lignes avec des tableaux, d'autres objets, etc ... mais complètement conforme : une paire clef/valeur n’apparaît qu'une fois, et la structure JSON est bien respectée.
Même le tout petit bout de JSON que j'ai saisi en haut ne franchit pas les validateurs stricts et a exactement la même structure que mon fichier réel.
Par contre le fichier passe sans problème et sans modification les différents parseurs que j'ai essayé, qui apparemment sont moins stricts sur la conformité mais aux dépends des résultats qui ne peuvent plus être obtenus, car ne pouvant être indexé (ou alors je ne vois pas comment).
Pour rendre valide, sans supprimer de données, il faudrait mettre les 2 objets dans un tableau d'objets de cette façon :
Donc remplacer un
{ "foo" : "1", "bar" : "1" }
... de mon stream parsé. Tout le reste passe les validateurs JSON quand cette espèce d' "entête" est effacée, et pourtant le fichier fait des centaines de lignes avec des tableaux, d'autres objets, etc ... mais complètement conforme : une paire clef/valeur n’apparaît qu'une fois, et la structure JSON est bien respectée.
Même le tout petit bout de JSON que j'ai saisi en haut ne franchit pas les validateurs stricts et a exactement la même structure que mon fichier réel.
Par contre le fichier passe sans problème et sans modification les différents parseurs que j'ai essayé, qui apparemment sont moins stricts sur la conformité mais aux dépends des résultats qui ne peuvent plus être obtenus, car ne pouvant être indexé (ou alors je ne vois pas comment).
Pour rendre valide, sans supprimer de données, il faudrait mettre les 2 objets dans un tableau d'objets de cette façon :
[ { "foo": "1", "bar": "1" }, { "titi": "val1", "toto": "val2", "tutu": "val3" } ]
Donc remplacer un
} {par
},{, le premier
{du fichier par
[{et le dernier
}par
}]avant de soumettre le stream au parseur. Le plus simple est certainement, effectivement, de modifier le fichier,de le dumper puis de le rouvrir. Je me demandais si il n'y avait pas possibilité de modifier les données "au vol" :p ou si il n'est pas possible de dire au parseur d'ignorer une partie des données.
Utilisateur anonyme
Modifié par Whismeril le 13/03/2016 à 19:36
Modifié par Whismeril le 13/03/2016 à 19:36
Ha zut,
j'avais travaillé sur l'hypothèse que tu n'avais que des "Config", pour ta info ça donnait ça:
Quand j'étais petit, la mer Morte n'était que malade.
George Burns
j'avais travaillé sur l'hypothèse que tu n'avais que des "Config", pour ta info ça donnait ça:
- le fichier de test
{
"foo" : "1",
"bar" : "1"
}{
"titi" : "val1",
"toto" : "val2",
"tutu" : "val3"
}
{
"titi" : "val4",
"toto" : "val5",
"tutu" : "val6"
}{
"foo" : "1",
"bar" : "1"
}{
"titi" : "val7",
"toto" : "val8",
"tutu" : "val9"
}
- la classe
public class MyConfig { public string titi { get; set; } public string toto { get; set; } public string tutu { get; set; } public static List<MyConfig> Deserialize(string Filename) { List<MyConfig> mesConfigs = new List<MyConfig>(); Regex maRegex = new Regex("({\\r\\n "titi" : "(?<Titi>\\w+)",\\r\\n "toto" : "(?<Toto>\\w+)",\\r\\n "tutu" : "(?<Tutu>\\w+)"\\r\\n})+"); foreach(Match m in maRegex.Matches(File.ReadAllText(Filename))) { mesConfigs.Add(new MyConfig { titi = m.Groups["Titi"].Value, toto = m.Groups["Toto"].Value, tutu = m.Groups["Tutu"].Value }); } return mesConfigs; } }
- la récupération de la liste de MyConfig
List<MyConfig> configs = MyConfig.Deserialize("test.json");
Quand j'étais petit, la mer Morte n'était que malade.
George Burns
Utilisateur anonyme
Modifié par Whismeril le 13/03/2016 à 19:45
Modifié par Whismeril le 13/03/2016 à 19:45
Je pense que la solution est là
https://codes-sources.commentcamarche.net/source/24620-string-to-stream
Et ce string en entrée:
Si tu as bien une ligne qui commence par }{, il faudra aussi virer }
Quand j'étais petit, la mer Morte n'était que malade.
George Burns
https://codes-sources.commentcamarche.net/source/24620-string-to-stream
Et ce string en entrée:
string TexteSansMoins3Lignes = string.Join("\r\n", File.ReadAllLines("test.json").Skip(3));
Si tu as bien une ligne qui commence par }{, il faudra aussi virer }
Quand j'étais petit, la mer Morte n'était que malade.
George Burns
ryko1820
Messages postés
1677
Date d'inscription
dimanche 28 avril 2013
Statut
Membre
Dernière intervention
15 août 2021
276
Modifié par ryko1820 le 13/03/2016 à 21:26
Modifié par ryko1820 le 13/03/2016 à 21:26
Waou !!
Merci !!!, je vais regarder tout ça et voir ce que j'arrive à en faire.
Pour ceux que ça intéresse, l'adresse d'un validateur JSON : https://jsonlint.com/
Merci !!!, je vais regarder tout ça et voir ce que j'arrive à en faire.
Pour ceux que ça intéresse, l'adresse d'un validateur JSON : https://jsonlint.com/
ryko1820
Messages postés
1677
Date d'inscription
dimanche 28 avril 2013
Statut
Membre
Dernière intervention
15 août 2021
276
Modifié par ryko1820 le 14/03/2016 à 17:20
Modifié par ryko1820 le 14/03/2016 à 17:20
Hello,
avec ton aide (et celle de Visual studio :p) voilà ce que j'ai fait (ça tourne nickel !) :
En fait, je n'ai pas eu besoin de convertir la string en stream car c'est un textReader qu'attends le serializer (et que renvoyait StreamReader ici), ce qui donne :
... je lis pas mal de JSON dans ce prog que j'écris, (j'ai un peu tendance aussi bien sous Linux que dans Windows ou sur le web (en Webservices) à en mettre partout, fichier de config, historisation, IO BDD, etc ...) mais les autres je les écris moi-même ce qui me permet de m'assurer de leur validité ...
Voilà donc une combine qui permets de corriger un JSON au vol :-)
(et accessoirement de convertir une string en textReader) ...
Encore merci Whismeril
J'ai corrigé l'exemple pour qu'il soit fonctionnel tel-quel pour peu qu'un fichier "config.json" (au format "foireux" décrit plus haut) existe dans "%addpdata%\myApp"
avec ton aide (et celle de Visual studio :p) voilà ce que j'ai fait (ça tourne nickel !) :
En fait, je n'ai pas eu besoin de convertir la string en stream car c'est un textReader qu'attends le serializer (et que renvoyait StreamReader ici), ce qui donne :
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication4 { class Program { static void Main(string[] args) { { Environment.CurrentDirectory = Environment.GetEnvironmentVariable("appdata") + "\\myProg"; // Mise en conformité JSON par retrait de l'objet inutile et mal formaté string coreConfNormalized = string.Join("\r\n", File.ReadAllLines(".\\config.json").Skip(3)).Replace("}{", "{"); // using (StreamReader configFile = File.OpenText(@".\\config.json")) // Création TextReader à partir de la String coreConfNormalized (fichier JSON corrigé) using (var configFile = new StringReader(coreConfNormalized)) { JsonSerializer serializer = new JsonSerializer(); MyConfig cfg = (MyConfig)serializer.Deserialize(configFile, typeof(MyConfig)); Console.WriteLine("titi : " + cfg.titi); Console.ReadLine(); } } } public class MyConfig { public string titi { get; set; } public string toto { get; set; } public string tutu { get; set; } } } }
... je lis pas mal de JSON dans ce prog que j'écris, (j'ai un peu tendance aussi bien sous Linux que dans Windows ou sur le web (en Webservices) à en mettre partout, fichier de config, historisation, IO BDD, etc ...) mais les autres je les écris moi-même ce qui me permet de m'assurer de leur validité ...
Voilà donc une combine qui permets de corriger un JSON au vol :-)
(et accessoirement de convertir une string en textReader) ...
Encore merci Whismeril
J'ai corrigé l'exemple pour qu'il soit fonctionnel tel-quel pour peu qu'un fichier "config.json" (au format "foireux" décrit plus haut) existe dans "%addpdata%\myApp"
Modifié par ryko1820 le 13/03/2016 à 16:47
Je vais essayer de comprendre la logique du parseur, et voir si il n'y aurait pas possibilité de gérer. Le souci c'est que je n'ai même pas d'erreur pour m'aider.