Search code examples
androidtype-conversionnormalizationandroid-roompojo

Android Room: Efficient way to transform json result into db object


Problem

I have a POJO parsed from an API call which looks like this

public class Article {

  public Long id;

  @Expose
  @SerializedName("section")
  public String section;

  @Expose
  @SerializedName("title")
  public String title;

  @Expose
  @SerializedName("topics")
  public List<String> topics;

  @Expose
  @SerializedName("media")
  public List<Media> media;
}

For the sake of minimizing redundancy and duplicates, I am looking to create a schema like this

@Entity(foreignKeys = { 
          @ForeignKey(entity = Article.class, parentColumns = "id", childColumns = "articleId"), 
          @ForeignKey(entity = Topic.class, parentColumns = "id", childColumns = "topicId"),
          @ForeignKey(entity = Media.class, parentColumns = "id", childColumns = "mediaId")
}
public class Articles {

    @PrimaryKey
    public Long articleId; 

    @ColumnInfo(name = "topic_id")
    public Long topicId;

    @ColumnInfo(name = "media_id")
    public Long mediaId;
}

@Entity
public class Article {
    // Left out
}

@Entity
public class Media {
    // Left out
}

As you can see, when I call the DAO methods to access the database, I can not just pass in the pojo object directly (unless I am mistaken about this). I believe I need to transform the object to one which matches the database entity model.

Question

Does the Android Framework provide a natural way to convert from POJO to the database model object? Is there a way to do this other than manually converting it myself?

Things I've Tried

  • I know that I can implement the conversion inside a method within my DAO interface. But then I would have to create a new object and set all the values manually.
  • I initially thought typeconverters would work but they seem to convert individual columns.

Solution

  • All you have to do is use @Embedded annotation for your POJO(Model Class) which will refer to another class. then create a type converter class.

    @Embedded(prefix = "media")
    private Media media;
    
    @TypeConverters({TypeConvertorClass.class})
    @Database(entities = {Article .class,Media.class}, version = 1, exportSchema = false)
    public abstract class `DataBaseExample` extends RoomDatabase {
    }
    
    
    public class Converters {
        @TypeConverter
        public static ArrayList<String> fromString(String value) {
            Type listType = new TypeToken<ArrayList<String>>() {}.getType();
            return new Gson().fromJson(value, listType);
        }
     
        @TypeConverter
        public static String fromArrayList(ArrayList<String> list) {
            Gson gson = new Gson();
            String json = gson.toJson(list);
            return json;
        }
    }
    
    
    public class TypeConvertorClass {
        @TypeConverter
        public static Media getMedia(String longId) {
            return longId== null ? null : new Meida();
        }
    }
    
    @Entity(tableName = "Article")
    public class Article {
        @ColumnInfo (name = "article_id")
        public Long id;
        
        @Expose
        @SerializedName("section")
        public String section;
    
        @Expose
        @SerializedName("title")
        public String title;
    
        @Expose
        @SerializedName("topics")
        public List<String> topics;
    
        @Embedded(prefix = "media") // We need relation to Media table
        @Expose
        @SerializedName("media")
        public List<Media> media;
    }
    
    public class Media {
        @ColumnInfo (name = "media_id")
        public Long id;
    }