In the process of web development, data interaction is required, which requires the related format of the interactive data so that the data can be passed between the client and the server. There are typically 2 formats of data: 1, xml;2, JSON. In general, JSON is used to pass data. This article is about some of the issues and recommendations that are encountered when converting between JSON and objects in Java. First, there are two concepts for JSON:
The JSON object (JavaScript object Notation,javascript objects notation). This seems to exist only as a bit of JavaScript customization, but it is independent of language and platform as a grammar. It's just that normally we use JSON format when the client (browser) passes data to the server, and this format is used to represent JavaScript objects. It is made up of a series of "Key-value", such as {"id": 1, "name": "Kevin"}, which is somewhat similar to how the map key-value pairs are stored. The JSON object described in Java actually refers to the Jsonobject class, which is usually named after each third party's Jsonjar package, and the different jar packages are slightly different from their internal implementations.
A JSON string. The conversion between a JSON object and a JSON string is a process of serialization and deserialization, which is analogous to the serialization and deserialization of a Java object. The data in the network is passed through a string, or a binary stream, and so on, that is, when the client (browser) needs to pass the data in JSON format, the string is passed in the network at this time, and the server side is of course the string (string type) after receiving the data. Sometimes you need to convert the JSON string to a JSON object and do the next step (string type to Jsonobject type).
The clarity of the above two concepts basically clarifies the JSON data format, or also called the JSON syntax. Java for the JSON jar package has many, the most "commonly used" is the "Net.sf.json" to provide the jar package, this article is to emphasize that this is the pit bag, although the pit, but has a wide range of applications. In fact, there are other excellent JSON package for us to use, such as Ali claims the fastest JSON package--fastjson, as well as Google's Gson, as well as Jackson. Try, or do not use "Net.sf.json" package, not only have pits, and is already very old, and can not be in the idea of the download to the source, MAVEN warehouse show it 2010 in the 2.4 version stopped updating. Let's talk about the 2 bugs I've known about "Net.sf.json" (which I think are bugs) and how these 2 bugs are generated.
JSON pit Package--net.sf.json1 in Java. When a Java object transforms a JSON object, all methods that begin with get are converted
What does this mean, for example, the following Java objects exist.
1 PackageSfjson;2 3 Importjava.util.List;4 5 /**6 * Created by Kevin on 2017/12/1.7 */8 Public classStudent {9 Private intID;Ten PrivateList<long>Courseids; One A Public intgetId () { - returnID; - } the - Public voidSetId (intID) { - This. ID =ID; - } + - PublicList<long>Getcourseids () { + returnCourseids; A } at - Public voidSetcourseids (list<long>courseids) { - This. Courseids =Courseids; - } - - PublicString GetSQL () {//The method that gets the SQL statement in this class does not have a corresponding property field in return"This is SQL."; - } to}
When we convert the student object to a JSON object, we want the converted JSON format to be:
1 {2 "id": 1,3 "Courseids": [1, 2, 3]4 }
However, the jsonobject json = jsonobject.fromobject (student) using the "Net.sf.json" package; The result of the API conversion is:
That is to say, "Net.sf.json" gets the method that begins with the public modifier get in the Java object and defines the suffix as the "key" of the JSON object, and defines the return value of the Get Start method as the "value" of the corresponding key. Note that the public modifier get starts with a method and has a return value.
I think this is an unreasonable conversion rule. If I define a method in a Java object, just because this method is "get" at the beginning and has a return value as the "Key-value" of the converted JSON object, wouldn't it be exposed? Or is it directly exposed to the console console of the front end when it is returned to the client (browser)? The author prescribes this conversion rule, and I think the probable reason is that since you define it for the public method and named get, it is intentional to expose this method to the client that called it to get it. But I still think it's unreasonable, even I define it as a bug. My definition may not be reasonable, because according to my measurements found that not only the "Net.sf.json" package will be converted according to this rule, Fastjson and Jackson also according to this rule, but Google's Gson did not follow this rule to the object to JSON conversion.
by Jsonobject JSON = Jsonobject.fromobject (student), the constructed student object is converted to a JSON object, as described earlier in this article. After entering this method, the overloaded method of Fromobject (object, Jsonconfig) continues to be called, and in this overloaded method it is instanceof to determine whether the object objects to be converted are enumerations, annotations, and so on, and these special types will have a special method of judging. Here is an ordinary Java Pojo object, so it goes into _fromobject (object, Jsonconfig), there are some judgments in this method, and finally the JSON object is created by calling Defaultbeanprocessing. This method is the key, in which also continues to get the "property descriptor" through the Propertyutils.getpropertydescriptors (bean) method, is actually to get the method with GET, It is encapsulated here as a propertydescriptor. This student in this class will get 4, respectively: GetClass, GetId, Getcourseids, GetSQL.
In fact, PropertyDescriptor package has been very detailed, what read and write methods have been assigned value.
For example, this getsql method has been parsed into the propertydescriptor. After that, some methods are filtered out by this class, for example, the GetClass method is not a method in Pojo, so it is not necessary to convert it to a JSON object. The acquisition of PropertyDescriptor is through Beaninfo#getpropertydescriptors, and BeanInfo's acquisition is through New Introspector (Beanclass, NULL, Use_ All_beaninfo). Getbeaninfo (); The following approach will be reached in the end.
Private throws introspectionexception { ... = Gettargetmethodinfo (); // This method calls Getpublicdeclaredmethods, and you can see that the public method is actually found, and that it is all public methods, including wait, etc. PropertyDescriptor pds[] = Gettargetpropertyinfo (); // filter According to certain rules, filter rules are all in this method, is to select the public modifier with a get prefix and return value method ...
The source code of the Net.sf.json a brief analysis, and found that indeed, as the conjecture, the specific source of more space is limited need to view the tracking.
2. Conversion errors,list<long> when JSON objects are converted to Java objects
The title of a sentence is not clear, this question, I am very certain that it is a bug.
There is now {"id": 1, "Courseids": a JSON string of [three-to-three]}, which needs to be converted to the student object mentioned above, with two attribute fields of type int and list<long> in the student object. This means that the JSON string should be converted to the corresponding data type.
String json = "{\" id\ ": 1, \" courseids\ ": []}"= (Student) Jsonobject.tobean (Jsonobject.fromobject (JSON), Student. class ); System.out.println (Student.getcourseids (). Get (instanceof Long);
The above output should be true, but unfortunately it is false. It is a long type at compile time, but an integer at run time. This has to be said to be a hole, and the other three JSON package did not appear this error. So I'm sure it's a bug. To see how this bug happened in Net.sf.json, you also need to compare the source code to see it yourself. I was interrupting. When debug went deep, I found out that Net.sf.json for the processing of integer data, this method was found Numberutils#createnumber, which is the type of data that is judged when the data is fetched from the string. The intention is to think that if the number with "L" or "L" will be treated as long, from here to see the final result should be right AH.
CaseL: CaseL: if(Dec = =NULL&& Exp = =NULL&& (Numeric.charat (0) = = '-' && isdigits (numeric.substring (1)) | |isdigits (numeric))) { Try { returnCreatelong (numeric); } Catch(NumberFormatException var11) {returnCreatebiginteger (numeric); } } Else { Throw NewNumberFormatException (str + "is not a valid number."); }
It is true that so far Net.sf.json has accurately judged the data type by its number identifier, and the problem is that it needs to be stored in the Jsonobject after the value has been obtained and its data type, while the deposit process is jsonutils# Transformnumber The existence of this method, the existence of this method, at least at present seems purely superfluous.
1 Public StaticNumber transformnumber (number input) {2 if(InputinstanceofFloat) {3 return NewDouble (input.tostring ());4}Else if(InputinstanceofShort ) {5 return NewInteger (Input.intvalue ());6}Else if(InputinstanceofByte) {7 return NewInteger (Input.intvalue ());8}Else {9 if(InputinstanceofLong) {TenLong max =NewLong (2147483647L); One if(Input.longvalue () <= max.longvalue () && input.longvalue () >= -2147483648l) {//even if the original type is long, but as long as it is in the integer range, it will eventually be converted to an integer. A return NewInteger (Input.intvalue ()); - } - } the - returninput; - } -}
The above code clearly shows the culprit, whether it is a long (long type in the integer range), including Byte, short is converted to an integer. It is not clear where the meaning of this piece of code is. The exact data type is determined by the letter after the number, and then the exact data type is converted once, which leads to the bug mentioned at the beginning. The problem is almost impossible to avoid, so the best way is not to use it.
These two pits are discovered by accident, it is recommended or not to use the Net.sf.json JSON package has not been maintained, another point, the Net.sf.json package on the JSON format is not so strict, if the format "{" id ": 1," Courseids ":" [ "}", in the other three packets will throw an exception, but Net.sf.json will not.
This is a public number that can give the programmer a buff.
Net.sf.json package in Java about JSON and object transfer in the pit