Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 分配空值';在Gson中,双字段的自定义序列化_Java_Serialization_Gson - Fatal编程技术网

Java 分配空值';在Gson中,双字段的自定义序列化

Java 分配空值';在Gson中,双字段的自定义序列化,java,serialization,gson,Java,Serialization,Gson,我正在尝试使用Gson自定义序列化将以下类序列化为Json public class Product{ public String prodId; public Double prodPrice; } 我想检查Double属性(prodPrice)的值是否为“-1.0”,如果为“-1.0”,则为字段赋值为null。我已经编写了下面的Gson自定义序列化程序来完成它 public class GsonUtil { public static String getJSONString

我正在尝试使用Gson自定义序列化将以下类序列化为Json

public class Product{
   public String prodId;
   public Double prodPrice;
}
我想检查Double属性(prodPrice)的值是否为“-1.0”,如果为“-1.0”,则为字段赋值为null。我已经编写了下面的Gson自定义序列化程序来完成它

public class GsonUtil {

public static String getJSONString(Object input) throws Exception {
    if (input == null) {
        throw new Exception("JSON Conversion failed. Input string is null");
    }

    try {

        JsonSerializer<Double> dser = getDoubleSerializer();

        Gson gson = new GsonBuilder().serializeNulls()
                .registerTypeAdapter(Double.class, dser)
                .create();

        String jsonStr = gson.toJson(input);

        if (jsonStr == null) {
            throw new Exception("Json String is null");
        }
        return jsonStr;

    } catch (Exception e) {

    }
    return null;
}

private static JsonSerializer<Double> getDoubleSerializer() {
    JsonSerializer<Double> ser = new JsonSerializer<Double>() {


        public JsonElement serialize(Double dval, Type arg1,
                JsonSerializationContext arg2) {

            if(!(dval.equals(-1.0))){
                return new JsonPrimitive(dval);
            }
            else{
                Double retVal = null;
                return new JsonPrimitive(retVal);
            }

        }
    };
    return ser;
}

}
公共类GsonUtil{
公共静态字符串getJSONString(对象输入)引发异常{
如果(输入==null){
抛出新异常(“JSON转换失败,输入字符串为空”);
}
试一试{
JsonSerializer dser=getDoubleSerializer();
Gson Gson=new GsonBuilder().serializeNulls()
.registerTypeAdapter(Double.class,dser)
.create();
字符串jsonStr=gson.toJson(输入);
if(jsonStr==null){
抛出新异常(“Json字符串为空”);
}
返回jsonStr;
}捕获(例外e){
}
返回null;
}
私有静态JsonSerializer getDoubleSerializer(){
JsonSerializer ser=新的JsonSerializer(){
公共JsonElement序列化(双dval,类型arg1,
JsonSerializationContext(arg2){
如果(!(dval.等于(-1.0))){
返回新的JsonPrimitive(dval);
}
否则{
双retVal=null;
返回新的JsonPrimitive(retVal);
}
}
};
返回ser;
}
}
当我执行此操作时,自定义序列化程序不工作,当我尝试分配除null之外的其他值时,相同的自定义序列化工作正常

请让我知道,如果我做了一些错误的事情,让我知道,如果它可以实现使用任何其他方式。
多谢各位

您可以有一个
Gson
实例,而不是每次您可能需要这种反序列化时都创建另一个实例。Gson支持可以绑定到特定对象字段并用
@JsonAdapter
注释的特殊类型适配器。请注意,除非使用此注释对其他相同类型的对象进行注释,否则它不会影响这些对象,因此保留了原始Gson配置

因此,
Product.java
可以为
prodPrice
字段添加注释:

最终类产品{
@SerializedName(“prodId”)
字符串id;
@JsonAdapter(SpecialDoubleTypeAdapter.class)
@序列化名称(“产品价格”)
双倍价格;
}
现在,只需创建一个符合您需求的特殊类型适配器:

final类SpecialDoubleTypeAdapter
扩展类型适配器{
私有静态最终类型适配器specialDoubleTypeAdapter=新的specialDoubleTypeAdapter();
//Gson甚至可以使用私有构造函数来实例化它本身
私有SpecialDoubleTypeAdapter(){
}
//如果需要手动实例化它
静态类型适配器getSpecialDoubleTypeAdapter(){
返回specialDoubleTypeAdapter;
}
@凌驾
@抑制警告(“资源”)
公共无效写入(最终JsonWriter out,最终双精度值)
抛出IOException{
//如果没有提供值或被认为是“非法”的,则将该值写为null(不过,这是一个很好的检查和使用右手表达式的地方)
如果(值!=null | |值<0){
out.值(value);
}否则{
out.nullValue();
}
}
@凌驾
公共双读(最终JsonReader in)
抛出IOException{
最终JsonToken标记=in.peek();
交换机(令牌){
大小写为空:
//读取空标记,这是必需的
in.nextNull();
返回null;
案件编号:
//将数字标记读为double
最终双d=in.nextDouble();
//假设负价格应该为空,而不仅仅是-1.0
返回d>=0?d:空;
//基于意见的案例组:可以使用默认值
//但在我看来,显式映射是显式的
案例开始\u数组:
案例结束单元阵列:
案例开始对象:
案例结束对象:
案例名称:
大小写字符串:
大小写布尔值:
案例结束文件:
抛出新的MalformedJsonException(“意外令牌:+令牌”);
//所以这永远不会发生,除非Gson有一天添加一个新的代币。。。
违约:
抛出新断言错误(“决不能发生”);
}
}
}
做一个小测试:

publicstaticvoidmain(最终字符串…args){
最终Gson Gson=新Gson();
测试(gson,“{\'prodId\”:“good\”,“prodPrice\”:100});
测试(gson,“{\'prodId\”:“bad\”,“prodPrice\”:-1}”);
}
专用静态无效测试(最终Gson Gson、最终字符串json){
最终产品Product=gson.fromJson(json,Product.class);
打印(“产品”);
打印(产品id);
打印件(“价格”);
out.println(产品价格);
}
上述演示将产生:

产品质量好,价格100.0
产品不良,价格无效

编辑1 序列化程序存在一些设计问题。最主要的一点是,如果发生异常,您的代码会吞下它,很抱歉,当我看到
Double retVal=null时,我错过了它;返回新的JsonPrimitive(retVal)。请不要这样做——否则您的代码将永远不会对严重问题保持沉默。接下来,您可以重新显示异常,它将得到以下结果:

java.lang.NullPointerException
    at com.google.gson.JsonPrimitive.isPrimitiveOrString(JsonPrimitive.java:278)
    at com.google.gson.JsonPrimitive.setValue(JsonPrimitive.java:101)
    at com.google.gson.JsonPrimitive.<init>(JsonPrimitive.java:56)
    at q42278197.m2.Q42278197$1.serialize(Q42278197.java:77)
    at q42278197.m2.Q42278197$1.serialize(Q42278197.java:71)
    at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243)
    at com.google.gson.Gson.toJson(Gson.java:669)
    at com.google.gson.Gson.toJson(Gson.java:648)
    at com.google.gson.Gson.toJson(Gson.java:603)
    at com.google.gson.Gson.toJson(Gson.java:583)
    at q42278197.m2.Q42278197.getJSONString(Q42278197.java:58)
    ... 7 more

请注意,使用了Java8Lambda,但您可以轻松地将其转换为匿名类。还请注意,您可以有一个Gson实例。这可能就是您所需要的,因为Gson本身可以处理null,等等。

当它确定值为
-1
并返回一个
JsonPrimitive
并指定
null
值时会发生什么?是否跳过该字段?我没有收到任何错误,同时无法看到任何响应。我得到的只是一个空白的答复