question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Crash when JSON is being serialized to Entity

See original GitHub issue

Basics

  • ObjectBox version (are using the latest version?): 1.0.0
  • Reproducibility: always

Reproducing the bug

Description

I’m getting some JSON from a REST call to a remote server and when the object is being created from the JSON object it crashes.

I have a just two entities for now, with a 1 to 1 relation. Each User entity has one UserSchoolDetails in it and all the information is passed in the JSON.

When I try to save the entry to the box it crashes.

Code

public static void updateUser() {
   //get the Box
   Box<User> userBox = SmartAlumni.boxStore.boxFor(User.class);
   
   //store the logged in User
    userBox.put(SmartAlumni.currentUser);
}
long __assignedId = collect313311(cursor, entity.id, PUT_FLAG_COMPLETE,
                __id10, wallet, 0, null,
                0, null, 0, null,
                __ID_userSchoolDetailsId, entity.userSchoolDetails.getTargetId(), __id8, __id8 != 0 ? dateOfBirth.getTime() : 0,
                __ID_is_admin, entity.getIs_admin() ? 1 : 0, 0, 0,
                0, 0, 0, 0,
                0, 0, 0, 0);

Logs & stackstraces

FATAL EXCEPTION: main
Process: com.pacent.smartalumni, PID: 21845
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
at io.objectbox.relation.ToOne.getTargetIdField(ToOne.java:248)
at io.objectbox.relation.ToOne.getTargetId(ToOne.java:236)
at com.pacent.smartalumni.data.models.UserCursor.put(UserCursor.java:100)
at com.pacent.smartalumni.data.models.UserCursor.put(UserCursor.java:16)
at io.objectbox.Box.put(Box.java:380)
at com.pacent.smartalumni.utils.Utilities.updateUser(Utilities.java:56)
at com.pacent.smartalumni.presentation.signup.SignInActivity.onDataLoaded(SignInActivity.java:132)
at com.pacent.smartalumni.presentation.signup.SignInActivity.onDataLoaded(SignInActivity.java:34)
at com.pacent.smartalumni.data.remote.SignUpDataSource$1.onResponse(SignUpDataSource.java:37)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

this is the JSON I get from the REST call

{"date_of_birth":"Aug 25, 2017 5:39:15 PM","email":"dami@kornetmail.com","first_name":"damilola","id":0,"is_admin":false,"last_name":"ola","name":"dami","phone_number":"1111111111","_id":"59a052b381ee2c1ae2effdd9","school_details":{"checkIdOfTargetForPut":false,"debugRelations":false,"resolvedTargetId":0,"targetId":0,"virtualProperty":false},"wallet":"59a6d36bda891ea63bb35d49"}

Entities

@Entity
public class User implements IUser {
    @Id
    public long id;

    @SerializedName("school_details")
    public ToOne<UserSchoolDetails> userSchoolDetails;
}
@Entity
public class UserSchoolDetails {
    @Id
    public long id;
}

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:16 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
rohitgupta1694commented, Oct 9, 2017

@jirevwe I just look into this issue and what i encountered is Retrofit2 is not aware of ToMany and ToOne type and also @greenrobot has already mentioned this thing in #104 .

I can share my model with the workaround. I am having a User Model which internally is related to Profile Picture Model coming from API Service and Location Model. I am using Retrofit2 to get the prepared User Model.

So my workaround in this issue is to provide @Transient annotation to ProfilePicture and Location type data members (as they will act as temporary data members and will not be stored into the db) and then add two new data members to the class as ToOne<ProfilePicture> and ToOne<Location> :

@Entity
public class User {
   @Id(assignable = true)
   @Expose
   @SerializedName("id")
   private long id;
   @Expose
   @Transient
   @SerializedName("location")
   private Location location;
   @Expose
   @SerializedName("age")
   private long age;
   @Expose
   @SerializedName("bio")
   private String bio;
   @Expose
   @SerializedName("dob")
   private String dob;
   @Expose
   @SerializedName("education")
   private String education;
   @Expose
   @SerializedName("email")
   private String email;
   @Expose
   @SerializedName("full_name")
   private String fullName;
   @Expose
   @SerializedName("gender")
   private String gender;
   @Expose
   @Transient
   @SerializedName("profile_picture")
   private ProfilePicture profilePicture;
   @Expose
   @SerializedName("username")
   private String username;
   @Expose
   @SerializedName("verified")
   private Boolean verified;
   @Expose
   @SerializedName("work")
   private String work;

   private ToOne<Location> locationRelation;
   private ToOne<ProfilePicture> profilePictureRelation;

   public long getId() {
       return id;
   }
   public Long getAge() {
       return age;
   }
   public String getBio() {
       return bio;
   }
   public String getDob() {
       return dob;
   }
   public String getEducation() {
       return education;
   }
   public String getEmail() {
       return email;
   }
   public String getFullName() {
       return fullName;
   }
   public String getGender() {
       return gender;
   }
   public String getUsername() {
       return username;
   }
   public Boolean getVerified() {
       return verified;
   }
   public String getWork() {
       return work;
   }
   public Location getLocation() {
       return location;
   }
   public ProfilePicture getProfilePicture() {
       return profilePicture;
   }
   public ToOne<ProfilePicture> getProfilePictureRelation() {
       return profilePictureRelation;
   }
   public ToOne<Location> getLocationRelation() {
       return locationRelation;
   }

   public void setId(long id) {
       this.id = id;
   }
   public void setAge(long age) {
       this.age = age;
   }
   public void setBio(String bio) {
       this.bio = bio;
   }
   public void setDob(String dob) {
       this.dob = dob;
   }
   public void setEducation(String education) {
       this.education = education;
   }
   public void setEmail(String email) {
       this.email = email;
   }
   public void setFullName(String fullName) {
       this.fullName = fullName;
   }
   public void setGender(String gender) {
       this.gender = gender;
   }
   public void setUsername(String username) {
       this.username = username;
   }
   public void setVerified(Boolean verified) {
       this.verified = verified;
   }
   public void setWork(String work) {
       this.work = work;
   }
   public void setLocation(Location location) {
       this.location = location;
   }
   public void setProfilePicture(ProfilePicture profilePicture) {
       this.profilePicture = profilePicture;
   }
   public void setLocationRelation() {
       locationRelation.setTarget(location);
   }
   public void setProfilePictureRelation() {
       profilePictureRelation.setTarget(profilePicture);
   }
}

Before storing the user model into the objectbox just call these two methods. As these methods will set the relation between user and the below models.

E.g.

private void OnSuccessFullySignedIn(SignUpSignInResponse signUpSignInResponse) {
       User user = signUpSignInResponse.getUser();
       user.setLocationRelation();
       user.setProfilePictureRelation();
       boxStore.boxFor(User.class).put(user);


      // Do the required after storing the data to ObjectBox.
   }

I hope this could resolve you problem as well.

1reaction
jirevwecommented, Oct 9, 2017

Hmm… Nice workaround. Actually I already switched to another database. I can close this issue now then…

Read more comments on GitHub >

github_iconTop Results From Across the Web

serialization - Is this a bug in JSON.NET or Entity Framework ...
Types that implement ISerializable are serialized as JSON objects. When serializing, only the values returned from ISerializable.
Read more >
Fixing JSON Self Referencing Loop Exceptions
When building applications that use JSON, you'll often have to deal with looping. Here's the real solution to fixing JSON self-referencing ...
Read more >
How to allow some kinds of invalid JSON with System.Text.Json
Json. Serialization) Specifies the property name that is present in the JSON when serializing and deserializing.
Read more >
JSON Serialization - Unity Manual
If the JSON data contains values that do not map to fields in MyClass , then the serializer ignores those values. If the...
Read more >
[Solved]-VS 2013 Crash When Using JSON Deserialize ...
Related Query · Getting exception when using DateTime. · Is there a guarantee on the order in which the Dispose() method is called...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found