Dans le processus de développement Web, l'interaction des données est indispensable, ce qui nécessite le format pertinent des données interactives à spécifier afin que les données puissent être transmises entre le client et le serveur. Il existe généralement deux types de formats de données: 1. XML; 2. JSON. D'une manière générale, JSON est utilisé pour transmettre des données. Cet article présente plusieurs problèmes rencontrés lors de la conversion de JSON et d'objets en Java et de suggestions connexes.
Tout d'abord, nous avons deux concepts pour JSON:
Objet JSON (Notation d'objet JavaScript, notation d'objet JavaScript). Cela semble être un bit JavaScript personnalisé, mais il est spécifique à la langue et à la plate-forme en tant que syntaxe. Cela signifie simplement que normalement lorsque nous passons des données au côté serveur (navigateur), nous utilisons le format JSON, et ce format est utilisé pour représenter les objets JavaScript. Il se compose d'une série de "valeurs clés", telles que {"id": 1, "nom": "kevin"}, qui est quelque peu similaire à la façon dont les paires de valeurs clés de carte sont stockées. L'objet JSON décrit dans Java fait réellement référence à la classe JSONObject, qui est généralement nommé d'après ce nom dans chaque package jsonjar tiers. Différents packages JAR ont des implémentations internes légèrement différentes.
JSON String. La conversion entre les objets JSON et les chaînes JSON est un processus de sérialisation et de désérialisation, qui est comme la sérialisation et la désérialisation des objets Java. La transmission de données dans le réseau est effectuée via des chaînes, ou des flux binaires, etc. C'est-à-dire que lorsque le client (navigateur) doit transmettre des données au format JSON, la chaîne est transmise sur le réseau à l'heure actuelle, et le côté serveur aura bien sûr également une chaîne (type de chaîne) après avoir reçu les données. Parfois, il est nécessaire de convertir la chaîne JSON en un objet JSON, puis d'effectuer l'opération suivante (le type de chaîne est converti en type JSONObject).
Les deux concepts ci-dessus clarifient essentiellement le format de données de JSON, ou également appelé syntaxe JSON. Il existe de nombreux packages en pot pour JSON à Java. Le plus "couramment utilisé" est le package JAR fourni par "net.sf.json". Cet article se concentrera sur ce paquet. Bien qu'il soit PIT, il dispose d'un large éventail d'applications. En fait, il existe d'autres excellents forfaits JSON à utiliser, comme Fastjson, qu'Alibaba prétend être le package JSON le plus rapide, GSON de Google et Jackson. Essayez d'utiliser le package "net.sf.json". Non seulement il y a des pièges, mais il est également très ancien, donc il ne peut pas télécharger le code source dans l'idée. Le référentiel Maven montre qu'il a été arrêté dans la version 2.4 en 2010. Parlons des deux bogues que je connais déjà sur «net.sf.json» et comment ces deux bogues ont été générés.
Package JSON Pit en Java - net.sf.json
1. Lorsque les objets Java convertissent les objets JSON, toutes les méthodes commençant par Get seront converties.
Qu'est-ce que cela signifie, par exemple, les objets Java suivants sont disponibles.
package sfjson; import java.util.list; / ** * créé par Kevin le 2017/12/1. * / classe publique Student {private int id; Liste privée <long> Coursides; public int getID () {return id; } public void setid (int id) {this.id = id; } Liste publique <long> getCourseIDIDS () {return CourseId; } public void setCourseIDIDS (list <long> CourseIDS) {this.courseIDS = CourseId; } public String getsql () {// La méthode pour obtenir des instructions SQL dans cette classe n'a pas le champ d'attribut correspondant return "Ceci est sql."; }}Lorsque nous convertissons l'objet Student en objet JSON, nous espérons que le format JSON converti devrait être:
{"id": 1, "Coursides": [1, 2, 3]}Cependant, le résultat après la conversion de JSONObject JSON = JSONObject.FromObject (Student); L'API est:
En d'autres termes, on peut deviner que "net.sf.json" obtient la méthode qui commence par le modificateur public Get dans l'objet Java et définit son suffixe comme la "clé" de l'objet JSON, et définit la valeur de retour de la méthode qui commence par la "valeur" de la clé correspondante. Notez que c'est la méthode qui commence par le modificateur public Get et a une valeur de retour.
Je pense que c'est une règle de conversion déraisonnable. Si je définis une méthode dans un objet Java, et juste parce que cette méthode commence par "Get" et a une valeur de retour, elle sera exposée? Ou est-il exposé à la console de la console frontale lorsqu'il est renvoyé au client (navigateur)? L'auteur stipule cette règle de conversion. La raison approximative que je pense est: puisque vous la définissez comme une méthode publique et que vous l'avez nommée, elle exposait intentionnellement cette méthode afin que le client l'appelle a le droit de l'obtenir. Mais je pense toujours que c'est déraisonnable, et même je le définis comme un bug. Il n'est peut-être pas raisonnable pour moi de définir de cette façon, car selon mon test réel, non seulement le package "net.sf.json" sera converti selon cette règle, mais Fastjson et Jackson suivent également cette règle, mais GSON de Google ne convertit pas les objets en JSON selon cette règle.
Convertissez l'objet étudiant construit en un objet JSON via JSONObject JSON = JSONObject.FromObject (Student); et l'élève est comme décrit ci-dessus. Après avoir entré cette méthode, la méthode surchargée FromObject (Object, JSONConfig) continuera d'être appelé. Dans cette méthode surchargée, l'instance OFF sera utilisée pour déterminer si l'objet objet à convertir est l'énumération, l'annotation et d'autres types. Ces types spéciaux auront des méthodes de jugement spéciales. Voici un objet Java Pojo ordinaire, il entrera donc dans _FromObject (objet, jsonconfig), et il y aura des jugements dans cette méthode, et enfin, l'objet JSON est créé en appelant defaultBeanProcesing. Cette méthode est la clé et continuera d'obtenir le "descripteur de propriétés" via PropertyUtils.getPropertyDescriptors (Bean). En fait, il s'agit d'obtenir la méthode avec GET, qui est encapsulée en tant que Descripteur de propriété ici. Cette classe d'étudiants aura 4, à savoir: GetClass, GetId, GetCourseids, GetSQL.
En fait, PropertyDescriptor est encapsulé en détail et toutes les méthodes de lecture et d'écriture ont été attribuées.
Par exemple, cette méthode GetSQL a été analysée dans le Spinscripteur Property dans la figure ci-dessus. Ce qui suit est filtré certaines méthodes à travers cette classe. Par exemple, la méthode GetClass n'est pas une méthode dans POJO, il n'a donc pas besoin d'être converti en un objet JSON. Le PropertyDescriptor est obtenu via BeanInfo # GetPropertyDescriptors, et le Beaninfo est obtenu via un nouvel introspector (BeanClass, Null, use_all_beaninfo) .getBeanInfo (); Et puis vous atteindrez enfin la méthode suivante.
privé beaninfo getBeanInfo () lève IntrospectionException {… MethodDescriptor mds [] = getTargetMethodInfo (); // Cette méthode appellera GetPublicDeclaredMethods. Vous pouvez voir qu'il recherche en effet des méthodes publiques, et toutes les méthodes publiques, y compris l'attente et d'autres propriétéScriptors PDS [] = getTargetPropertyInfo (); // Filtrez selon certaines règles. Les règles de filtrage sont toutes dans cette méthode, qui est de sélectionner la méthode où le modificateur public a un préfixe Get et une valeur de retour ...J'ai brièvement analysé le code source de net.sf.json et j'ai constaté que, comme je suppose, le code source spécifique est relativement grand et limité dans l'espace, et doit être vu et suivi par moi-même.
2. Lors de la conversion d'un objet Java en un objet JSON, une erreur de conversion se produira sur la liste <long>
Le titre ne peut pas être expliqué clairement dans une phrase, et je suis très sûr que ce problème est un bug.
Maintenant, il y a une chaîne JSON de {"id": 1, "Coursides": [1,2,3]}, et il doit être converti à l'objet étudiant mentionné ci-dessus. Il y a deux champs d'attribut de type int et list <long> dans l'objet étudiant, ce qui signifie que cette chaîne JSON doit être convertie en type de données correspondant.
String JSON = "{/" id / ": 1, /" Coursides / ": [1,2,3]}"; étudiant étudiant = (étudiant) jsonObject.tobean (jsonObject.fromObject (json), étudiant.class); System.out.println (étudiant.getcourseIdS (). Get (0) instance long);La sortie ci-dessus doit être vraie, mais malheureusement, elle est fausse. Pour être précis, il est long au moment de la compilation, mais entier au moment de l'exécution. Cela doit être considéré comme un piège, et aucun des trois autres packages JSON n'a une telle erreur. Je suis donc sûr que c'est un bug. Voyons comment ce bogue se produit dans net.sf.json. Vous devez également comparer le code source vous-même pour le voir. Pendant que j'approfondissais constamment le débogage des points d'arrêt, j'ai découvert que lorsque net.sf.json traitait les données entières, j'ai découvert cette méthode NumberUtils # Createenumber. Cette classe juge son type de données lors de l'extraction des données d'une chaîne. L'intention d'origine est de traiter le nombre aussi longtemps s'il a "L" ou "L" après. À partir de ce point de vue, le résultat final devrait être correct.
case 'l': case 'l': if (dec == null && exp == null && (Numeric.Charat (0) == '-' && isDigits (Numeric.SubString (1)) || IsDigits (Numeric))) {try {return CreateLong (Numeric); } catch (NumberFormatexception var11) {return CreateBigInteger (Numeric); }} else {Throw New NumberFormatexception (str + "n'est pas un nombre valide."); }En effet, jusqu'à présent, net.sf.json a jugé avec précision le type de données via l'identifiant après le numéro. Le problème réside dans le fait qu'après avoir obtenu cette valeur et son type de données, il doit être stocké dans JSONObject. La méthode jsonutils # transformNumber existe pendant le processus de stockage. L'existence de cette méthode est au moins purement extravagante dans la vue actuelle.
Public Static Number TransformNumber (Number Input) {if (entrée instanceof float) {return new double (input.toString ()); } else if (entrée instanceof short) {return new Integer (input.intValue ()); } else if (entrée instanceof byte) {return new Integer (input.intValue ()); } else {if (entrée instanceof long) {long max = new long (2147483647l); if (input.longValue () <= max.longValue () && input.longValue ()> = -2147483648l) {// Même si le type d'origine est long, tant qu'il est dans la plage entière, il sera finalement converti en Intime. return nouvel entier (input.intvalue ()); }} retour de retour; }}Le code ci-dessus montre clairement le coupable, qu'il s'agisse du type long (le type long dans la plage entière), y compris l'octet et court, il sera converti en entier. Je ne comprends pas quelle est la signification de ce code. Le type de données précis doit être déterminé sur la base des lettres après le numéro, et le type de données précis doit être converti à nouveau plus tard, ce qui conduit au bogue mentionné au début. Ce problème est presque inévitable, donc la meilleure façon est de ne pas l'utiliser.
Ces deux pièges ont été découverts par hasard. Il est recommandé de ne pas utiliser le package JSON de net.sf.json qui n'a pas été maintenu. De plus, le package net.sf.json n'est pas si strict dans la vérification du format JSON. Si un tel format est "{" id ": 1," Coursides ":" [1,2,3] "}", une exception sera lancée dans les trois autres packages, mais ne le fera pas.
L'article ci-dessus traite en détail des pièges de JSON et de transfert d'objets en Java. C'est tout le contenu que je partage avec vous. J'espère que cela pourra vous donner une référence et j'espère que vous pourrez soutenir Wulin.com plus.