6
votes

Est-il possible de détecter de mauvaises citations dans une chaîne JSON mal formée, puis d'analyser la chaîne comme JSON correctement?

J'utilise des rails 4.2.3. Je parcaie Json envoyé par un tiers (je ne contrôle pas comment ce Json est formé). J'ai remarqué que les taht ils envoient très parfois mal Json, comme si xxx

remarque dans ce qui précède, le mot "graisse", avec les guillemets, vissait le reste du JSON. Dans mon code de rails, je analysais le Json, comme ... xxx

Bien que je puisse prendre des erreurs lorsque JSON ne pars pas correctement, je me demande s'il y a une façon de rendre compte de ces citations mal placées, corrigez-les de manière à ce que la chaîne ci-dessus ne constitue pas un mauvais JSON, puis analyser correctement le JSON.


3 commentaires

Bien sûr, vous pouvez essayer de corriger le JSON, mais que feriez-vous avec {"A": "," B ": 1"} . Vous ne devriez pas accepter JSON invalide, car il n'est pas propre et imprévisible et vous pouvez simplement vous échapper. par exemple. \ "gras \" serait valide.


Je voudrais corriger le JSON mal formé (de la manière dont j'ai décrit ci-dessus) si possible. Si Taht n'est pas possible, c'est une réponse aussi.


Vous auriez essentiellement besoin de faire votre propre fixateur JSON. Peut-être diviser la chaîne où vous trouvez "," et d'autres variations avec des espaces / nouvelles lignes entre, puis prenez tout après chaque : , prenez la première et la dernière double citation et enfin remplacer chaque double citation par un seul, par exemple. Ensuite, vous pourriez l'utiliser dans l'analyseur. Une autre manière serait de contacter le fournisseur JSON et de leur demander de bien vouloir fournir un JSON valide.


7 Réponses :


2
votes

Si vous savez exactement quelles malformations pourraient survenir, vous pourriez réussir à faire des solutions de contournement folle comme à l'aide de RegEx pour correspondre et corrigez la chaîne avant de l'analyser comme JSON:

(?:")([^,:"]*"[^,:"]*"[^,:"]*)(?:")


4 commentaires

Merci. Mon knwoeldge d'expression et de rails réguliers est encore un peu limité. Je vois que cette exécressive identifie les mauvaises citations, mais comment puis-je utiliser ceci pour résoudre la situation?


@Mike - J'ai ajouté un POP complet dans le message d'origine.


Bonne affaire. Comme j'utilise des rails pour le faire (par opposition à JS), comment cela jouerait-il à ROR?


@Mike - Désolé, je ne suis actuellement aucune raille qui parle. Ma réponse n'a pas été intégrée comme une solution mise en œuvre complète de toute façon. Je voulais juste vous montrer comment vous pourriez résoudre le problème. Fondamentalement, ce sera la même chose dans Ruby sur les rails de toute façon, juste une syntaxe différente.



0
votes

Essayez de manipuler une erreur en utilisant Commencer la manipulation d'exception de sauvetage comme, xxx

Ceci augmentera une exception lorsqu'un format JSON est invalide et informer le propriétaire de la source pour modifier le JSON. >


1 commentaires

Je ne comprends pas comment cette réponse m'aidera à détecter les types de malformations de devis que j'ai décrites et que je les fixe davantage.



1
votes

Utilisation de regex, vous pouvez vérifier avant d'analyser les guillemets \ "\" code> suivi d'un mot \ w + code> et finissant par \ " code>. Si vous trouvez qu'il utilise gsub code> pour remplacer la phrase avec des guillemets simples et un lookback "\ '\\ 1 \' code>.

t='{"DisplayName":""fat" Tony Elvis ","Time":null,"OverallRank":19,"AgeRank":4}'
t=t.gsub(/\"\"(\w+)\"/, '"\'\\1\'') 


0 commentaires

1
votes

Je pense que vous devez faire / avoir certains hypothèses sur le "JSON" toujours vrai. Si, par exemple, les objets JSON ont toujours un ordre fixe d'attributs, cela pourrait aider beaucoup, surtout si seuls les attributs simples sont problématiques.

J'essaierais de faire correspondre xxx

Ensuite, remplacez-la à l'aide d'une fonction de "fixateur", qui utilise probablement simplement les groupes de capture et réécrit certains objet créé par ad-hoc en réellement valide JSON valide. Une variation serait, d'élargir le (. *?) pour ne correspond à quelque chose que quelque chose est faux.

Cependant, toute l'approche devient plus compliquée avec des attributs facultatifs et encore plus avec un ordre flexible d'attributs (tous pourraient toujours être gérables).

Comme vous l'avez très bien pu remarquer, cela ne fonctionne que si l'hypothèse en haut est vraie. Selon les hypothèses que vous pouvez faire, la solution peut être très simple. Cependant, tout devient difficile à manier, si ces éléments mal formés sont complètement irréguliers. Alors ... bonne chance, je suppose. Veuillez poster les hypothèses sur le JSON que vous croyez être vraie, si vous avez besoin d'une aide supplémentaire. S'il n'y en a pas cependant, un programme devra deviner , ce que nous voulions dire. Je veux dire, quelqu'un pourrait signifie: xxx

si les guillemets sont échappés de manière erronée, vous auriez un problème. Mais comme je l'ai dit, vous devez faire certains hypothèse sur le "JSON". Je veux dire, l'hypothèse habituelle à propos de JSON est que c'est valable, car sinon, ce n'est tout simplement pas JSON.


0 commentaires

0
votes

Ce n'est pas un problème facile à résoudre. Surtout parce que la rédaction d'un analyseur JSON n'est pas triviale et là, je doute que vous puissiez adapter un analyseur pour travailler comme vous le souhaitez.

Si je devais absolument résoudre ce problème par programme (comme appellé à demander au vendeur de réparer leur JSON), je le ferais probablement avec une ramification.

Prendre votre exemple String JSON:
{"DisplayName": "" Fat "Tony Elvis", "Time": NULL, "GallRank": 19, "Agerank": 4}

Écoutez d'abord l'entrée dans des personnages et itérez-les sur eux. Chaque fois qu'un devis est rencontré recueil et testez les deux possibilités: la citation fait partie du JSON et la citation fait partie des données.

Chaque fois que vous trouvez une citation, vous branchez, alors après deux devis, il y aura quatre solutions valides possibles, après quatre citations, il y aura 16 solutions possibles, etc.

Comme vous le faites, streamez chaque solution possible dans un panier JSON JSON ( comme celui-ci ) et surveiller des exceptions. Si on est lancé, supposons que la solution possible ne fonctionne pas et le jette. Je jetterais aussi après une profondeur de 4 (ou 8, si vous attendez des cordes cibles dans vos données). En limitant la profondeur, vous arrêterez également des solutions telles que {"A \": \ "b \", \ "C"} d'être renvoyé comme valide.

réellement construire cela prendrait au moins quelques heures, probablement quelques jours à faire, et il reste une bonne possibilité que cela signalera de faux positifs. Il sera également lent comme un chien car vous devrez analyser potentiellement des milliers de flux JSON différents en utilisant RUBY, au lieu de analyser une utilisation d'une bibliothèque C JSON.

Vous pouvez atténuer certaines des questions de performance en ajoutant toutes les solutions possibles à une file d'attente et utilisez un bassin de threads de travailleur pour aller chercher des solutions potentielles et travailler dessus; Mais maintenant, nous parlons peut-être une semaine de travail pour nettoyer ces données avec un script.


0 commentaires


0
votes

Comme les autres affiches ont mentionné, si votre service ne vous fournit pas JSON valide, il n'ya aucun moyen de vous assurer que vous pourrez lire les données qu'ils vous envoient. Ce que vous pouvez faire cependant, est de trouver des cas courants et d'essayer de corriger ceux-ci.

Si vos documents JSON suivent le schéma de votre exemple, écrire un petit analyseur vous aidera à essayer de lire des documents malformés qui y adhèrent. p>


échappatoire Double citations strong> -Ce sera de nouveau cocher vos devis doubles non évalués, même s'ils ne sont pas équilibrés. P>

invalid =  '{"DisplayName":""fat" Tony" Elvis","Time":null,"OverallRank":19,"AgeRank":4}'

# strip away { and }
tailhead = invalid[1..-2]

props = tailhead.split(/,(?=".+"\s*:)/)

pairs = props.map {|p| p.split(/:(?=(?:".*"|\d+|null|false|true)$)/i)}

escaped = pairs.map do |k,v|
    # is this a string property?
    string = v[/^"(.*?)"$/, 1]
    string ? [k, "\"#{string.gsub(/"/,'\\"')}\""] : [k,v]
end

valid = '{' + escaped.map {|p| p.join(':')}.join(',') + '}'

json_data = JSON.parse(valid)


0 commentaires