【问题标题】:Gson. Deserialize to java object list of new elements with null id格森。反序列化为具有空 id 的新元素的 java 对象列表
【发布时间】:2014-12-22 18:18:19
【问题描述】:

我有 ol 和 li 元素树。我正在动态添加这个元素。在此之后,我想将它们反序列化为 java 对象。不幸的是,我收到了一个错误:

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/derp] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause java.lang.NullPointerException at com.derp.generic.model.GenericModel.getId(GenericModel.java:28)

我知道这是因为我的新元素没有 ID。但这意味着要这样,因为 Id 是在数据库服务器上生成的。通常 id 我会做这样的思考(通过 setter 创建对象分配参数,但没有 id)不会有错误。在持久化之后,这个新对象将获得一个 id。

我在这里想要达到的效果相同。正确反序列化后,我想让这个对象持久化,这将为他创建一个 Id。

但我必须告诉我的 Gson 构建器允许 null,或者不要尝试设置未声明的参数(为 null)。

这是我的代码:

public List<SkeletonElement> toObject(String jsonObject) {
    Gson gson = new GsonBuilder()
                .serializeNulls()
                .registerTypeAdapter(Long.class, new LongTypeAdapter())
                .create();
    List<SkeletonElement> list = gson.fromJson(jsonObject, new TypeToken<List<SkeletonElement>>(){}.getType());
    return list;
}

自定义适配器应该可以解决问题:

package com.derp.generic.helpers;

import java.io.IOException;

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

public class LongTypeAdapter extends TypeAdapter<Long>{
@Override
public Long read(JsonReader reader) throws IOException {
    if(reader.peek() == JsonToken.NULL){
        reader.nextNull();
        return null;
    }
    String stringValue = reader.nextString();
    try{
        Long value = Long.valueOf(stringValue);
        return value;
    }catch(NumberFormatException e){
        return null;
    }
}
@Override
public void write(JsonWriter writer, Long value) throws IOException {
    if (value == null) {
        writer.nullValue();
        return;
    }
    writer.value(value);
}
}

声明 id 的通用模型:

@MappedSuperclass
public abstract class GenericModel<T extends GenericModel<?>> {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;


    public long getId() {return id;}
    public void setId(long id) {this.id = id;}

    public GenericModel() {
    }

    public GenericModel(Long id) {
        super();
        this.id = id;
    }
}

最后是带有空id对象的json对象

[
    {
        "name": "Title1",
        "id": "1",
        "type": "SkeletonJobElement",
        "parent_id": "null",
        "children": [
            {
                "name": "Title11",
                "id": "2",
                "type": "SkeletonJobElement",
                "parent_id": "1",
                "children": [
                    {
                        "name": "Title111",
                        "id": "5",
                        "type": "SkeletonFileElement",
                        "parent_id": "2",
                        "children": []
                    },
                    {
                        "name": "Title112",
                        "id": "6",
                        "type": "SkeletonFileElement",
                        "parent_id": "2",
                        "children": []
                    }
                ]
            }
        ]
    },
    {
        "name": "Title2",
        "id": "3",
        "type": "SkeletonJobElement",
        "parent_id": "null",
        "children": [
            {
                "name": "Title21",
                "id": "4",
                "type": "SkeletonJobElement",
                "parent_id": "3",
                "children": []
            }
        ]
    },
    {
        "name": "Title3",
        "id": "null",
        "type": "SkeletonJobElement",
        "parent_id": "null",
        "children": []
    }
]

【问题讨论】:

  • GenericModel 类的第 28 行发生错误,但您提供的类只有约 19 行。你截断了吗?检查堆栈跟踪底部的第一个错误。无论如何,根据错误,您的GenericModel 子类的id 看起来是null。尝试将id getters/setters 的类型更改为Long,以匹配它们正在变异/访问的实例变量。
  • 是的。我已经截断了不需要的行。第 28 行是 public long getId() {return id;} 它是 null 因为 null 一开始在 json 中!

标签: java json gson deserialization primary-key


【解决方案1】:

此方法返回原始long。您不能从此方法返回 null

public long getId() { return id; }

修改返回类型为Long。该方法返回的实例变量可以是null,但方法本身不能。

public Long getId() { return id; }

对 setter 执行相同操作。

public void setId(Long id) { this.id = id; }

您还可以在返回之前检查null

public long getId() { id == null ? 0L : id.longValue(); }

【讨论】:

  • 现在它可以工作了。谢谢。从原始的 long 对象变为 Long 对象就足够了
【解决方案2】:

如果可能,更改 getId 以返回 Long 对象而不是原始 long。自动转换为原始 long 会导致您的空指针异常。

【讨论】:

    猜你喜欢
    • 2021-08-14
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多