0E-8 java 科学技术法问题(Gson 坑) Java返回Bigdecimal类型数据时“0E-8“及小数点多个0的问题

1,915 阅读2分钟

方案一:GsonBuilder registerTypeAdapter 注册类型适配器实现!


static {
    GsonBuilder builder = new GsonBuilder();
    builder.setDateFormat("yyyy-MM-dd HH:mm:ss");
    builder.registerTypeAdapter(BigDecimal.class,new BigDecimalSerializer());
    GSON = builder.create();
}



public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
    Preconditions.checkArgument(
    typeAdapter instanceof JsonSerializer 
    || typeAdapter instanceof JsonDeserializer
    || typeAdapter instanceof InstanceCreator 
    || typeAdapter instanceof TypeAdapter);
    
    if (typeAdapter instanceof InstanceCreator) {
        this.instanceCreators.put(type, (InstanceCreator)typeAdapter);
    }

    if (typeAdapter instanceof JsonSerializer
    || typeAdapter instanceof JsonDeserializer) {
        TypeToken<?> typeToken = TypeToken.get(type);
        this.factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));
    }

    if (typeAdapter instanceof TypeAdapter) {
         this.factories.add(
             TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter)
         );
    }

    return this;
}


public class BigDecimalSerializer  implements JsonSerializer<BigDecimal> {
    @Override
    public JsonElement serialize(BigDecimal bigDecimal, Type type, JsonSerializationContext jsonSerializationContext) {
        if(bigDecimal == null){
            return new JsonPrimitive(BigDecimal.ZERO.stripTrailingZeros().toPlainString());
        }else{
            return new JsonPrimitive(bigDecimal.stripTrailingZeros().toPlainString());
        }
    }

}


/**
 * A simple utility class used to check method Preconditions.
 * 一个实用的程序类 用来检查方法 Preconditions
 * <pre>
 * public long divideBy(long value) {
 *   Preconditions.checkArgument(value != 0);
 *   return this.value / value;
 * }
 * </pre>
 *
 * @author Inderjeet Singh
 * @author Joel Leitch
 */
public final class $Gson$Preconditions {
  private $Gson$Preconditions() {
    throw new UnsupportedOperationException();
  }

  public static <T> T checkNotNull(T obj) {
    if (obj == null) {
      throw new NullPointerException();
    }
    return obj;
  }

  public static void checkArgument(boolean condition) {
    if (!condition) {
      throw new IllegalArgumentException();
    }
  }
}




方案二: Gson 返回的List 重新赋值为 BigDecimal.ZERO;

public static void main(String[] args) {

    BigDecimal rewardPercent = new BigDecimal("0.00000000000000");

    // 默认打印:0E-8
    System.out.println(rewardPercent);
    // 格式化打印:0.00000000
    System.out.println(rewardPercent.toPlainString());

    // BigDecimal.ZERO 与 0E-8 比较大小:true
    System.out.println(BigDecimal.ZERO.compareTo(rewardPercent) == 0);
    BusinessBill businessBill =new BusinessBill();

    if( rewardPercent==null || BigDecimal.ZERO.compareTo(rewardPercent) == 0){
        rewardPercent= BigDecimal.ZERO;
    }

    businessBill.setConsumeMoney(rewardPercent);
    System.out.println(GsonUtil.getGson().toJson(businessBill));
}

方案三: 自定义 CustomerBigDecimalSerialize


import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Objects;

public class CustomerBigDecimalSerialize extends JsonSerializer<BigDecimal> {
    @Override
    public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if(Objects.nonNull(value)) {
        	//返回到前端的数据为数字类型,前端接收有可能丢失精度
			//gen.writeNumber(value.stripTrailingZeros());
        	//返回到前端的数据为字符串类型
            gen.writeString(value.stripTrailingZeros().toPlainString());
            //去除0后缀,如果想统一进行保留精度,也可以采用类似处理
        }else {//如果为null的话,就写null
            gen.writeNull();
        }
    }
}

//在vo类字段中对字段加上@JsonSerialize注解
  @JsonSerialize(using = CustomerBigDecimalSerialize.class)
  private BigDecimal totalExchangeBtc; //抵扣电费的usdt兑换的btc总量
  @JsonSerialize(using = CustomerBigDecimalSerialize.class)
  private BigDecimal perTotalExchangeBtc; //兑换的btc总量对应每份的btc
  @JsonSerialize(using = CustomerBigDecimalSerialize.class)
  private BigDecimal exchangeUsdtPrice; //兑换时usdt的价格

1,实现一个类型适配器(TypeAdapter)

自定义类型适配器需要实现两个接口:

序列化: JsonSerializer


@Override
public JsonElement serialize(BigDecimal bigDecimal, Type type1, JsonSerializationContext jsonSerializationContext) {
    if(bigDecimal == null){
        return new JsonPrimitive(BigDecimal.ZERO.stripTrailingZeros().toPlainString());
    }else{
        return new JsonPrimitive(bigDecimal.stripTrailingZeros().toPlainString());
    }
}

反序列化 :  JsonDeserializer


 
  public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)  
       throws JsonParseException;  

注册类型适配器

 

  1. Gson gson = new GsonBuilder()  
  2.                     .registerTypeAdapter(Timestamp.class, new TimestampAdapter())  
  3.                     .create();