我有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)
我知道这种情况正在发生,因为我的新元素dosnt有一个id。但这意味着这样,因为Id是在数据库服务器上生成的。通常id我会这样做A think(通过setter创建对象分配参数,但没有id)将没有错误。坚持下去后,这个新对象将获得一个id。
我想在这里实现同样的目标。在正确的反序列化后,我想坚持这个对象,这将为他创建一个Id。
但我必须告诉我的Gson构建器允许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;
}
}
json对象的结尾为空id对象
[
{
"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": []
}
]
答案 0 :(得分:2)
此方法返回原始long
。您无法从此方法返回null
。
public long getId() { return id; }
将返回类型修改为Long
。此方法返回的实例变量可以是null
,但方法本身不能。
public Long getId() { return id; }
对设定者也这样做。
public void setId(Long id) { this.id = id; }
您还可以在返回前检查null
。
public long getId() { id == null ? 0L : id.longValue(); }
答案 1 :(得分:0)
如果可能,更改getId以返回Long对象而不是原始long。自动转换为原始long会导致空指针异常。