如何向JSONObject中存入保留小数位的Double类型数值(以34.0为例)——解决WebService传输时整数型Double丢失小数点及末尾0的问题
I’ve run into this exact quirk with org.json’s JSONObject before—it automatically strips trailing .0 from integer-like floating-point values because JSON’s number type doesn’t distinguish between integers and floats, and the library optimizes output for brevity. Here are a few practical solutions depending on your constraints:
Option 1: Store the value as a formatted string
If your backend can accept string representations of numeric values (or parse them correctly), format the number to retain the decimal place before adding it to the JSONObject:
JSONObject ctx = new JSONObject(); try { ctx.put("csrf", vfModel.getCsrf()); ctx.put("vid", vid); ctx.put("ns", ""); // Format to preserve one decimal place BigDecimal verValue = BigDecimal.valueOf(34.0); String formattedVer = new DecimalFormat("#.0").format(verValue); ctx.putOpt("ver", formattedVer); } catch (JSONException e) { e.printStackTrace(); Log.e(TAG, "JSONException null generateToken: " + e.getMessage()); }
This will output:
{"csrf":"VmpFPSxNakF5TVMwd01pMHhNbFF4TXpveE16b3pNaTQ1TkRSYSwwVUVJT3kycmh6SGRYY01EZ1BWR1I3LE0yTmtaV1V6","vid":"06690000005lUNp","ns":"","ver":"34.0"}
Option 2: Switch to a more flexible JSON library (Jackson/Gson)
org.json is minimal and offers little control over number serialization. If you can switch libraries, Jackson or Gson let you configure exactly how numbers are serialized:
Using Jackson:
Configure the ObjectMapper to retain decimal places for floating-point values, or force BigDecimals to be written with full precision:
ObjectMapper mapper = new ObjectMapper(); // Ensure BigDecimals are written without scientific notation and keep decimal places mapper.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true); // Build your data structure Map<String, Object> data = new HashMap<>(); data.put("csrf", vfModel.getCsrf()); data.put("vid", vid); data.put("ns", ""); data.put("ver", BigDecimal.valueOf(34.0)); // Convert to JSON string String json = mapper.writeValueAsString(data);
This outputs ver: 34.0 as a numeric value (not a string).
Using Gson:
Register a custom serializer for BigDecimal to enforce trailing .0 when needed:
Gson gson = new GsonBuilder() .registerTypeAdapter(BigDecimal.class, new JsonSerializer<BigDecimal>() { @Override public JsonElement serialize(BigDecimal src, Type typeOfSrc, JsonSerializationContext context) { // Add one decimal place if the value is an integer return new JsonPrimitive(src.scale() <= 0 ? src.setScale(1) : src); } }) .create(); // Build data map Map<String, Object> data = new HashMap<>(); data.put("csrf", vfModel.getCsrf()); data.put("vid", vid); data.put("ns", ""); data.put("ver", BigDecimal.valueOf(34.0)); // Convert to JSON string String json = gson.toJson(data);
Option 3: Extend JSONObject for custom number handling
If you must stick with org.json, create a custom subclass to override how numbers are stored:
public class CustomJSONObject extends JSONObject { @Override public JSONObject putOpt(String key, Object value) throws JSONException { if (value instanceof BigDecimal) { BigDecimal bd = (BigDecimal) value; // Force one decimal place if the value is an integer super.putOpt(key, bd.scale() == 0 ? bd.setScale(1) : bd); } else { super.putOpt(key, value); } return this; } }
Then use this custom class instead of the standard JSONObject:
CustomJSONObject ctx = new CustomJSONObject(); try { ctx.put("csrf", vfModel.getCsrf()); ctx.put("vid", vid); ctx.put("ns", ""); ctx.putOpt("ver", BigDecimal.valueOf(34.0)); } catch (JSONException e) { e.printStackTrace(); Log.e(TAG, "JSONException null generateToken: " + e.getMessage()); }
Why org.json does this:
JSON’s number type doesn’t distinguish between integers and floats, so org.json’s serializer optimizes output by stripping trailing .0 from values that are effectively integers. To override this behavior, you need to either enforce formatting via string conversion or use a library that gives you granular control over serialization.
内容的提问来源于stack exchange,提问作者Prince Authenticode

