objectbox-java icon indicating copy to clipboard operation
objectbox-java copied to clipboard

Improve relations to play nicer with server APIs (e.g. Retrofit, GSON, Jackson, Moshi, ...)

Open greenrobot opened this issue 7 years ago • 63 comments

If you get object data from another source (e.g. server) you can make those data objects also ObjectBox entities. One thing has to be considered: relations on ObjectBox currently rely on ToOne and ToMany types, which 3rd party libraries are not aware of.

A quick work around would probably be to walk through the object graph and replace List objects with ToMany objects.

However, we could also look into supporting plain java.util.Lists in some way. A put would have to detect the type and do some additional syncing to figure out what to do. Or maybe just plainly put all objects in the list?

greenrobot avatar Jun 01 '17 11:06 greenrobot

That would fix #95 for me.

FabianTerhorst avatar Jun 01 '17 11:06 FabianTerhorst

Not 100% certain how to implement it. Somewhat hesitant to enable putting entire lists as this may "encourage" it, which just might be wrong in other scenarios. Maybe having a new marker annotation to enable it?

greenrobot avatar Jul 21 '17 15:07 greenrobot

An annotation for automatic inserting lists would be great.

FabianTerhorst avatar Jul 21 '17 15:07 FabianTerhorst

Is there any news on this? Currently running into this exact same issue (of toOne's not being recognised by a 3rd party), and would love to keep on using ObjectBox without having to build costly wrappers around everything...

bloemy7 avatar Oct 04 '17 21:10 bloemy7

Seconded. Meanwhile, out of curiosity, what is the fix you guys are using? Something like order.forEach { order -> order.customer.target = order } ?

Vincent-Carrier avatar Oct 04 '17 23:10 Vincent-Carrier

Yep, with .setTarget(order). Seems like the right way around this for the moment.

bloemy7 avatar Oct 06 '17 11:10 bloemy7

Yes please. Would like to use an ObjectBox "entity" as a model of Retrofit responses too. Using Moshi for the json adapter. Please suggest a way to use these together.

KishoreBabuIN avatar Oct 26 '17 13:10 KishoreBabuIN

Any ETA on this? Looking to move from Realm to ObjectBox but this issue is making it difficult.

ecramer avatar Oct 27 '17 14:10 ecramer

I concur in regards to having an annotation based solution @ToOne @ToMany POJOS or in this case entities should not be closely tied to a database.

Having something like:

@Many List<Stuff> stuff

Would solve many of the issues here

ArthurSav avatar Nov 07 '17 10:11 ArthurSav

I have a class with ToMany object, and using retrofit as rest client. I am getting this error while loading data,

FATAL ERROR field com.company.entity.Receipt.receipt_items has type io.objectbox.relation.ToMany, got java.util.ArrayList

This is my class structure.

@Entity
public class Receipt implements Serializable {

    public ToMany<ReceiptItem> receipt_items;

    @Id
    public long id;
    public long receipt_no;
}

Issue is arraylist not mapping to ToMany object.

indrakumarprajapat avatar Jan 19 '18 20:01 indrakumarprajapat

@indrakumarprajapat Is this a JSON parsing error? For example with GSON you might have to create a type adapter for ToMany. -ut

greenrobot-team avatar Jan 22 '18 08:01 greenrobot-team

okay, I got it, but can you help me, how can I do that. i have little bit idea. but not sure how to do it exacly.

indrakumarprajapat avatar Jan 27 '18 11:01 indrakumarprajapat

@indrakumarprajapat Sorry, not here. Please look in the GSON documentation or ask for example on Stack Overflow for help. -ut

greenrobot-team avatar Jan 29 '18 06:01 greenrobot-team

Sorry for late reply, the issue is fixed by type adapter. thanks.

indrakumarprajapat avatar Feb 22 '18 12:02 indrakumarprajapat

I don't like this solution but it works. you have to implement JsonDeserializer.

    public  class MyDeserializer<T extends FromJson> implements JsonDeserializer<T> {
        @Override
        public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            try {
                T var = ((Class<T>) typeOfT).newInstance();
                var.fromJson(json.getAsJsonObject());
                return var;
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (Throwable e) {
                e.printStackTrace();
            }

            return null;
        }
    }

create Gson object to use with Retrofit

 Gson gson= new GsonBuilder()
                .registerTypeHierarchyAdapter(FromJson.class, new MyDeserializer())
                .create();

Retrofit retrofit = new Retrofit.Builder()
                .client(client)
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

FromJson interface and some example.

public interface FromJson {
    void fromJson(JsonObject jo) throws JSONException;
}

@Entity
public class Status implements FromJson  {
    public long id;
    public int code;
    public String message;

    public void fromJson(JsonObject jo) throws JSONException {
            this.code = jo.get("code").getAsInt();
            this.message = jo.get("message").getAsString();
    }
}

@Entity
public class Login implements FromJson  {
    public long id;
    public ToOne<User> user;
    public ToOne<Status> status;

    @Override
    public void fromJson(JsonObject jo) throws JSONException {
            Status s = new Status();
            s.fromJson(jo.get("status").getAsJsonObject());
            this.status.setTarget(s);
        
            User u = new User();
            u.fromJson(jo.get("user").getAsJsonObject());
            this.user.setTarget(u);
    }
}

Any example using TypeAdapter? example provided by @greenrobot-team is dead.

ferdavs avatar Feb 28 '18 11:02 ferdavs

@indrakumarprajapat How does the TypeAdapter work? Could U show me a simple demo ? Thks :)

VincentJ1989 avatar Mar 07 '18 03:03 VincentJ1989

I'm not sure any of the comments here directly reflect the case of simple nested objects, of the type that crop up all the time in JSON data feeds, e.g.:

{
   "name": "Acme Inc.",
   "location": {
      "longitude": 1.23456,
      "latitude": 6.54321
   }
}

Which might deserialize to...

public class Location
{
   private double longitude;
   private double latitude;
   // getters, setters etc.
}

@Entity
public class Business
{
   private String name;
   // HOW TO PERSIST THIS??
   private Location location;
}

These are a problem too, but we don't usually need an entity relationship here. Something more like Room's @Embedded annotation would be sufficient.

(I think this is more accurately covered by https://github.com/objectbox/objectbox-java/issues/217 which is marked as a duplicate of this issue.)

markwhitaker avatar Mar 26 '18 12:03 markwhitaker

objectbox+Retrofit

ferdavs avatar Apr 20 '18 15:04 ferdavs

I gave up because of this problem, and I don't think this data structure design is reasonable enough.

lgengsy avatar Jul 19 '18 04:07 lgengsy

@lgengsy Could you provide a little bit info for us, so we can fix it?

greenrobot avatar Jul 19 '18 05:07 greenrobot

@indrakumarprajapat How does the TypeAdapter work? Could U show me a simple demo ? Thks :)

uiiang avatar Jul 25 '18 02:07 uiiang

Quick poll: Do you mostly need this for List? Or is ToOne a hard requirement?

greenrobot avatar Jul 25 '18 19:07 greenrobot

At first, I thought this project could help me deal with data caching problems quickly. I tried it. When I met toMany and toOne, I found the project was getting more and more complicated. It took me a day or two to adjust my data structure. Finally, I found it too hard to change back.

lgengsy avatar Jul 30 '18 03:07 lgengsy

Any new solutions or workarounds? Or better look for another ORM? (Room?) Creating an adapter for each entity not really an option

Riabkov avatar Aug 01 '18 21:08 Riabkov

Any solutions for ToOne or ToMany to work with Retrofit?

hetang avatar Aug 03 '18 23:08 hetang

Is there any solution for deserialize ToOne Object Using Gson Converter ? @greenrobot @greenrobot-team

MhmDSmdi avatar Aug 19 '18 12:08 MhmDSmdi

Is there any update or any solution for working with Gson?

suleymanccelik avatar Sep 12 '18 08:09 suleymanccelik

@greenrobot @greenrobot-team Can you summarize the specific implementation? It is best to add to the document

wb1992321 avatar Oct 10 '18 02:10 wb1992321

I have the same issue. Please, implement annotation for ToOne.

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of io.objectbox.relation.ToOne (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

Xset-s avatar Oct 13 '18 21:10 Xset-s

java.lang.IllegalArgumentException: field .bean.SubscribeBean.cates has type io.objectbox.relation.ToMany, got java.util.ArrayList

@Backlink(to = "subscribeBean") private ToMany<NewsBean> cates;

I still can't find the exactly method to resolve this problem,could you give some example?retro+objectbox

xuzh2017 avatar Nov 13 '18 02:11 xuzh2017