简体   繁体   中英

Gson. Deserialize to java object list of new elements with null id

I have tree of ol and li elements. I am adding this element dynamically. After this I would like to deserialize them into java object. Unfortunatelly I am getting an error:

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)

I know this is happening cause my new elements dosnt have an id. But this meant to be that way, cause Id is generated on database server. Normally id I will do such A think (create object assign parameters throught setters, but without id) there will be no error. And after persist this new object will got an id.

The same I am trying to achieve here. After correct deserialisation I would like to make persist this object and that will create an Id for him.

But I have to tell my Gson builder to allow null, or to not try set parameter which isnt declared (is null).

Here is my code:

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;
}

Custom adapter which should to the trick:

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);
}
}

Generic model where id is declared:

@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;
    }
}

And json object with null id object at the end

[
    {
        "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": []
    }
]

This method returns a primitive long . You cannot return a null from this method.

public long getId() { return id; }

Modify the return type to Long . The instance variable that this method is returning can be null , but the method itself cannot.

public Long getId() { return id; }

Do the same with the setter.

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

You can also check for null before returning.

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

If possible change getId to return a Long object rather than a primitive long. The automatic conversion to primitive long causes your null pointer exception.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM