Use @Embedded from Room persistence Library beside Gson deserializer
Asked Answered
D

1

6

I use Google Room Persistence Library for saving data in database. in Room there is an annotation (@Embedded) :

you can use the @Embedded annotation to represent an object that you'd like to decompose into its subfields within a table. You can then query the embedded fields just as you would for other individual columns

@Entity
public class MyObject {

// nested class
public class GeneralInfo {

    public String ownerName;

    @PrimaryKey
    public long wellId;
}

@Embedded
public GeneralInfo generalInfo;

public long objectId;

// other fields
}

I use Gson to deserialize json string from REST API, I want Gson to deserialize GeneralInfo fields into MyObject fields directly. How can I do this?

I want Gson to deserialize MyObjects like this:

{
    objectId : 1
    wellId : 1
    ownerName : "Me"
}

NOT this

{
    generalInfo : {        
        wellId : 1
        ownerName : "Me"        
    } 
    objectId : 1
}

Is there any way other than using JsonAdapter ? I can write my own convertToJson and convertFromJson but I want to use Gson and it's better to use annotation to tell Gson "don't deserialize this embeddede object to a jsonObject, insert its field in its parent json fields"

Devisal answered 22/1, 2018 at 10:56 Comment(1)
Did you find a solution for this? I'm encountering the same problem right nowValaria
B
1

You can use a custom TypeAdaptor:

public static void main(String[] args) {
    final MyObject myObject = new MyObject("Fardwark", 123, 9999L);
    final String json = gson.toJson(myObject);
    System.out.println(json);

    final MyObject myObject2 = gson.fromJson(json, MyObject.class);
    final String json2 = gson.toJson(myObject2);
    System.out.println(json2);
}

private static final Gson gson = new GsonBuilder()
        .registerTypeAdapter(MyObject.class, new MyTypeAdapter())
        .create();

private static final class MyTypeAdapter extends TypeAdapter<MyObject> {

    @Override
    public void write(JsonWriter jsonWriter, MyObject myObject) throws IOException {
        jsonWriter.beginObject()
                .name("ownerName").value(myObject.generalInfo.ownerName)
                .name("wellId").value(myObject.generalInfo.wellId)
                .name("objectId").value(myObject.objectId)
                .endObject();
    }

    @Override
    public MyObject read(JsonReader jsonReader) throws IOException {
        String ownerName = null;
        int wellId = 0;
        long objectId = 0;

        jsonReader.beginObject();;

        for (int i = 0; i < 3; ++i) {
            switch (jsonReader.nextName()) {
                case "ownerName":
                    ownerName = jsonReader.nextString();
                    break;
                case "wellId":
                    wellId = jsonReader.nextInt();
                    break;
                case "objectId":
                    objectId = jsonReader.nextLong();
                    break;
            }
        }

        jsonReader.endObject();

        return new MyObject(ownerName, wellId, objectId);
    }
}

Output:

{"ownerName":"Fardwark","wellId":123,"objectId":9999}
{"ownerName":"Fardwark","wellId":123,"objectId":9999}
Blane answered 26/11, 2022 at 19:19 Comment(4)
this is a not generic solution...Dulcet
@Dulcet The question never asked for a "generic solution", whatever that actually means. It's a solution, and the only one as far as I know.Blane
please go and read the question. here're some highlights: "... any way other than using JsonAdapter ?" "... use Gson and it's better to use annotation to tell Gson "don't deserialize this embeddede object to a jsonObject, insert its field in its parent json fields""Dulcet
If you know of another, better way to do it then feel free to post your answer here.Blane

© 2022 - 2024 — McMap. All rights reserved.