In the process of web development, data interaction is indispensable, which requires the relevant format of interactive data to be specified so that data can be passed between the client and the server. Geralmente, existem dois tipos de formatos de dados: 1. XML; 2. JSON. De um modo geral, o JSON é usado para passar dados. Este artigo apresenta vários problemas encontrados ao converter JSON e objetos em Java e sugestões relacionadas.
Primeiro, temos dois conceitos para o JSON:
Objeto JSON (notação do objeto JavaScript, notação de objeto JavaScript). Este parece ser um bit JavaScript personalizado, mas é específico da linguagem e da plataforma como uma sintaxe. It just means that normally when we pass data to the server side (browser) we use JSON format, and this format is used to represent JavaScript objects. Consiste em uma série de "valores-chave", como {"id": 1, "Name": "Kevin"}, que é um pouco semelhante à maneira como os pares de valores de chave do mapa são armazenados. O objeto JSON descrito em Java realmente se refere à classe JsonObject, que geralmente recebe o nome desse nome em cada pacote JSONJAR de terceiros. Pacotes JAR diferentes têm implementações internas ligeiramente diferentes.
String json. The conversion between JSON objects and JSON strings is a process of serialization and deserialization, which is like the serialization and deserialization of Java objects. The data transmission in the network is performed through strings, or binary streams, etc. That is to say, when the client (browser) needs to pass data in JSON format, the string is passed on the network at this time, and the server side will of course also have a string (String type) after receiving the data. Às vezes, é necessário converter a string json em um objeto JSON e, em seguida, executar a próxima operação (o tipo de string é convertido em tipo JsonObject).
Os dois conceitos acima esclarecem basicamente o formato de dados do JSON, ou também chamados de sintaxe JSON. Existem muitos pacotes JAR para JSON em Java. O mais "comumente usado" é o pacote JAR fornecido por "net.sf.json". Este artigo se concentrará neste pacote de poço. Embora seja o poço, ele possui uma ampla gama de aplicações. De fato, existem outros excelentes pacotes JSON para usarmos, como Fastjson, que o Alibaba afirma ser o pacote JSON mais rápido, o GSON do Google e Jackson. Tente usar o pacote "net.sf.json". Não apenas existem armadilhas, mas também é muito antigo, tão antigo que não pode baixar o código -fonte na Idea. O repositório Maven mostra que foi interrompido na versão 2.4 em 2010. Vamos falar sobre os dois bugs que eu já sei sobre "net.sf.json" e como esses dois bugs foram gerados.
Pacote json pit em java - net.sf.json
1. Quando os objetos Java convertem objetos JSON, todos os métodos que começam com GET serão convertidos.
O que isso significa, por exemplo, os seguintes objetos Java estão disponíveis.
pacote sfjson; importar java.util.list;/*** Criado por Kevin em 2017/12/1. */public classe estudante {private int id; Lista privada <Long> CourseIds; public int getId () {return id; } public void setId (int id) {this.id = id; } list public <long> getCourseIds () {return souldingIds; } public void setCourseIds (list <long> curso) {this.courseIds = curso; } public string getsql () {// O método para obter instruções SQL nesta classe não possui o retorno do campo de atributo correspondente "Este é SQL."; }}Quando convertemos o objeto do aluno para o objeto JSON, esperamos que o formato JSON convertido seja:
{"Id": 1, "CourseIds": [1, 2, 3]}No entanto, o resultado após a conversão do JsonObject json = jsonObject.FromObject (Student); API é:
Em outras palavras, pode -se adivinhar que "net.sf.json" obtém o método que começa com o modificador público entrar no objeto Java e define seu sufixo como a "chave" do objeto JSON e define o valor de retorno do método que começa com o GET como o "valor" da chave correspondente. Observe que é o método que começa com o modificador público obtém e tem um valor de retorno.
Eu acho que esta é uma regra de conversão irracional. Se eu definir um método em um objeto Java, e apenas porque esse método começa com "Get" e tem um valor de retorno, ele será exposto? Ou está exposto ao console do front-end Console quando é devolvido ao cliente (navegador)? O autor estipula essa regra de conversão. A razão aproximada que eu acho é: como você o define como um método público e o nomeou, ele está intencionalmente expondo esse método para que o cliente que o chamasse tenha o direito de obtê -lo. Mas ainda acho que isso não é razoável, e até eu o defino como um bug. Pode não ser razoável para eu definir dessa maneira, porque, de acordo com meu teste real, não apenas o pacote "net.sf.json" será convertido de acordo com esta regra, mas Fastjson e Jackson também seguem essa regra, mas o GSON do Google não converte objetos para JSON de acordo com esta regra.
Converter o objeto de estudante construído em um objeto JSON através do JsonObject json = jsonObject.FromObject (Student); e o aluno é como descrito acima. Depois de inserir esse método, o método sobrecarregado doObject (Object, JSONCONFIG) continuará sendo chamado. Neste método sobrecarregado, a instância do INSPELHO será usada para determinar se o objeto a ser convertido é enumeração, anotação e outros tipos. Esses tipos especiais terão métodos especiais de julgamento. Aqui está um objeto Java Pojo comum, por isso entrará em _FromObject (Object, JSONCONFIG), e haverá alguns julgamentos nesse método e, finalmente, o objeto JSON é criado chamando DefaultBeanProcessing. Este método é a chave e continuará a obter o "descritor de propriedades" através do método PropertyUtils.getPropertyDescriptores (Bean). De fato, é para obter o método com get, que é encapsulado como um PropertyDescriptor aqui. Esta aula de estudante receberá 4, a saber: getclass, getid, getCourseIds, getsql.
De fato, o PropertyDescriptor é encapsulado em detalhes e todos os métodos de leitura e gravação foram atribuídos.
Por exemplo, esse método GetSQL foi analisado no PropertyDescriptor na figura acima. O seguinte é filtrado alguns métodos através desta classe. Por exemplo, o método getClass não é um método no POJO, por isso não precisa ser convertido em um objeto JSON. O PropertyDescriptor é obtido através do Beaninfo#getPropertyDescriptors, e o Beaninfo é obtido através de um novo introspector (Beansclass, Null, USE_All_Beaninfo) .getBeanInfo (); E então você finalmente alcançará o seguinte método.
Private Beaninfo getBeanInfo () lança introspecçãoException {… MethodDescriptor MDS [] = getTargetMethodinfo (); // Este método chamará getPublicDecLaredMethods. Você pode ver que ele está realmente procurando por métodos públicos e todos os métodos públicos, incluindo espera e outros PropertyDescriptores PDS [] = getTargetPropertyInfo (); // filtrar de acordo com certas regras. As regras de filtragem estão todas neste método, que é selecionar o método em que o modificador público tem um prefixo e um valor de retorno ...Analisei brevemente o código -fonte do net.sf.json e descobri que, como acho, o código -fonte específico é relativamente grande e limitado no espaço e precisa ser visualizado e rastreado por mim.
2. Ao converter um objeto Java em um objeto JSON, ocorrerá um erro de conversão na lista <long>
O título não pode ser explicado claramente em uma frase, e tenho certeza de que esse problema é um bug.
Agora, existe uma sequência JSON de {"id": 1, "CourseIds": [1,2,3]} e precisa ser convertido no objeto do aluno mencionado acima. Existem dois campos de atributo do tipo Int e List <long> no objeto do aluno, o que significa que essa sequência JSON deve ser convertida para o tipo de dados correspondente.
String json = "{/" id/": 1,/" cursoIds/": [1,2,3]}"; Student = (estudante) jsonObject.tobean (jsonObject.FromObject (json), Student.class);A saída acima deve ser verdadeira, mas infelizmente é falsa. Para ser mais preciso, é longo em tempo de compilação, mas inteiro no tempo de execução. Diz -se que isso é considerado uma armadilha, e nenhum dos outros três pacotes JSON tem esse erro. Então, tenho certeza de que é um bug. Vamos ver como esse bug ocorre em net.sf.json. Você também precisa comparar o código -fonte para visualizá -lo. Enquanto eu estava constantemente aprofundando o Debug Point, descobri que, quando net.sf.json estava processando dados inteiros, descobri esse método numberils#createNumber. Esta classe julga seu tipo de dados ao extrair dados de uma string. A intenção original é processar o número tanto se tiver "L" ou "L" depois dele. Desse ponto de vista, o resultado final deve estar correto.
case 'l': case 'l': if (dec == null && exp == null && (numeric.charat (0) == '-' && isDigits (numeric.substring (1)) || isdigits (numeric))) {try {return createLong (numérico); } catch (númeroFormatexception var11) {return createBigInteger (numeric); }} else {lança novo númeroFormatexception (str + "não é um número válido."); }De fato, até agora, Net.sf.json julgou com precisão o tipo de dados através do identificador após o número. O problema está no fato de que, depois de obter esse valor e seu tipo de dados, ele precisa ser armazenado no JsonObject. O método JsonUtils#TransformNumber existe durante o processo de armazenamento. A existência desse método é pelo menos puramente extravagante na visão atual.
número estático public static transformNumber (entrada de número) {if (Instância de entrada de float) {return new Double (input.toString ()); } else if (Instância de entrada de curta) {retorna new integer (input.intValue ()); } else if (Instância de entrada de byte) {return new integer (input.intValue ()); } else {if (Instância de entrada de long) {long max = new Long (2147483647L); if (input.longValue () <= max.longValue () && input.longValue ()> = -2147483648l) {// Mesmo que o tipo original seja longo, desde que esteja dentro do intervalo inteiro, ele será convertido para inteiro. retornar novo número inteiro (input.intValue ()); }} retornar entrada; }}O código acima mostra claramente o culpado, seja o tipo longo (o tipo longo dentro do intervalo inteiro), incluindo byte e curto, será convertido em número inteiro. Não entendo qual é o significado desse código. O tipo de dados preciso deve ser determinado com base nas letras após o número, e o tipo de dados preciso deve ser convertido novamente mais tarde, o que leva ao bug mencionado no início. Esse problema é quase inevitável, portanto, a melhor maneira é não usá -lo.
Essas duas armadilhas foram descobertas por acaso. Recomenda -se não usar o pacote json de net.sf.json que não foi mantido. Além disso, o pacote Net.sf.json não é tão rigoroso na verificação do formato JSON. Se esse formato for "{" ID ": 1," CourseIds ":" [1,2,3] "}", uma exceção será lançada nos outros três pacotes, mas net.sf.json não.
O artigo acima discute as armadilhas do JSON e a transferência de objetos em Java em detalhes. Este é todo o conteúdo que compartilho com você. Espero que possa lhe dar uma referência e espero que você possa apoiar mais o wulin.com.