x10 quitar que poner número numeros numero notación notacion muestre formato evitar convertir como cientifica java json gson

java - quitar - ¿Cómo evitar que Gson convierta un número largo(una cadena json) al formato de notación científica?



quitar formato notacion cientifica excel (6)

Necesito convertir la cadena json en un objeto java y mostrarlo como un largo. La cadena json es una matriz fija de números largos:

{numbers [ 268627104, 485677888, 506884800 ] }

El código para convertir funciona bien en todos los casos, excepto en los números que terminan en 0. Los convierte a un formato de número de notación científica:

public static Object fromJson(HttpResponse response, Class<?> classOf) throws IOException { InputStream instream = response.getResponseInputStream(); Object obj = null; try { Reader reader = new InputStreamReader(instream, HTTP.UTF_8); Gson gson = new Gson(); obj = gson.fromJson(reader, classOf); Logger.d(TAG, "json --> "+gson.toJson(obj)); } catch (UnsupportedEncodingException e) { Logger.e(TAG, "unsupported encoding", e); } catch (Exception e) { Logger.e(TAG, "json parsing error", e); } return obj; }

El resultado real: objeto Java: 268627104, 485677888, 5.068848E + 8

Observe que el último número se convierte a un formato de notación científica. ¿Alguien puede sugerir qué se podría hacer para solucionarlo, prevenirlo o deshacerlo? Estoy usando Gson v1.7.1


No encontré una solución a mi problema de números de formato gson que terminaban en 0 a notación científica. En su lugar, utilicé una solución alternativa para convertir esta notación científica en un doble que formateé con comas. "valor" es la cadena json.

private String formatNumber(String value) { double dValue = Double.parseDouble(value); String pattern = "#,###"; DecimalFormat formatter = new DecimalFormat(pattern); String newNumber = formatter.format(dValue); return newNumber; }

Esto no responde a la pregunta formulada, pero es un paso adicional para solucionar el problema y mostrar los números que requiere el sistema.


No es inteligente, pero aún así el método de trabajo es agregar "al principio y al final del número. Luego, una vez que el procesamiento haya terminado, elimínelo.


Otra solución es utilizar la clase JsonParser en su lugar. Esto devolverá las representaciones de objetos Gson (JsonElement) en lugar de una clase definida por el usuario, pero evita el problema de la conversión a notación científica.

import java.lang.reflect.Type; import java.util.Map; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; public class GsonTest { public static void main(String[] args) { String json = "{numbers:[268627104,485677888,506884800]}"; Gson gson = new Gson(); Type type = new TypeToken<Map<String, Object>>(){}.getType(); Map<String, Object> jsonMap = gson.fromJson(json, type); System.out.println("Gson output:"); System.out.println(jsonMap); JsonParser jsonParser = new JsonParser(); JsonElement jsonElement = jsonParser.parse(json); System.out.println("JsonParser output:"); System.out.println(jsonElement); } }

Salida de código:

Gson output: {numbers=[2.68627104E8, 4.85677888E8, 5.068848E8]} JsonParser output: {"numbers":[268627104,485677888,506884800]}


Si serializar una cadena es una opción para usted, puede configurar GSON para que lo haga con:

GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.setLongSerializationPolicy( LongSerializationPolicy.STRING ); Gson gson = gsonBuilder.create();

Esto producirá algo como:

{numbers : [ "268627104", "485677888", "506884800" ] }


Tengo el mismo problema, después de una investigación aquí es lo que encontré.

El comportamiento:

  • Gson
    Para un número sin parte fraccionaria, Gson lo convertiría en Double ,
  • Jackson
    Para un número sin parte fraccionaria, Jackson lo convertiría como Integer o Long , depende de qué tan grande sea el número.

Soluciones posibles:

  • Convierta el valor de retorno de Gson de Double a Long , explícitamente.
  • Utilice Jackson lugar.
    Prefiero esto.

Código - prueba de Jackson

ParseNumberTest.java:

import java.util.List; import org.testng.Assert; import org.testng.annotations.Test; import com.fasterxml.jackson.databind.ObjectMapper; /** * test - jackson parse numbers, * * @author eric * @date Jan 13, 2018 12:28:36 AM */ public class ParseNumberTest { @Test public void test() throws Exception { String jsonFn = "numbers.json"; ObjectMapper mapper = new ObjectMapper(); DummyData dd = mapper.readValue(this.getClass().getResourceAsStream(jsonFn), DummyData.class); for (Object data : dd.dataList) { System.out.printf("data type: %s, value: %s/n", data.getClass().getName(), data.toString()); Assert.assertTrue(data.getClass() == Double.class || data.getClass() == Long.class || data.getClass() == Integer.class); System.out.printf("%s/n/n", "------------"); } } static class DummyData { List<Object> dataList; public List<Object> getDataList() { return dataList; } public void setDataList(List<Object> dataList) { this.dataList = dataList; } } }

números.json:

{ "dataList": [ 150000000000, 150778742934, 150000, 150000.0 ] }

Como correr:

  • El caso de prueba se basa en Jackson & TestNG .
  • Ponga numbers.json en el mismo paquete que ParseNumberTest.java .
  • Ejecutar como prueba de prueba, luego imprimiría el tipo y el valor del resultado del análisis.

Salida:

data type: java.lang.Long, value: 150000000000 ------------ data type: java.lang.Long, value: 150778742934 ------------ data type: java.lang.Integer, value: 150000 ------------ data type: java.lang.Double, value: 150000.0 ------------ PASSED: test


Tuve un problema similar, y no solo convierte los enteros al doble, sino que en realidad pierde precisión para ciertos números largos, como se describe en esta pregunta relacionada .

Busqué esta conversión al método de read ObjectTypeAdapter , específicamente:

case NUMBER: return in.nextDouble();

Es posible que se pueda conectar un TypeAdapter for Object modificado, pero no pude hacer que funcionara, por lo que copié el método de read ( Object read(JsonReader in) ) a mi propio código y modifiqué las líneas anteriores para este :

case NUMBER: final String s = in.nextString(); try { return Integer.parseInt(s); } catch (NumberFormatException e) { // ignore } try { return Long.parseLong(s); } catch (NumberFormatException e) { // ignore } return Double.parseDouble(s);

Ojalá Gson hiciera esto por defecto ...

Luego puse las otras piezas de conexión en un método auxiliar que se parece a esto:

public static Object parse(final Reader r) { try (final JsonReader jr = new JsonReader(r)) { jr.setLenient(true); boolean empty = true; Object o = null; try { jr.peek(); empty = false; o = read(jr); } catch (EOFException e) { if (!empty) { throw new JsonSyntaxException(e); } } if (o != null && jr.peek() != JsonToken.END_DOCUMENT) { throw new JsonIOException("JSON document was not fully consumed."); } return o; } catch (IOException e) { throw new JsonIOException(e); } }

Así que ahora, en lugar de new Gson().fromJson(r, Object.class) , llamo parse(r) .

Esto me funciona bien porque quiero poder analizar los datos json con cualquier estructura, pero si tiene una clase en particular a la que está apuntando, probablemente solo necesite eliminar las ocurrencias de Object dentro de los miembros de esa clase.