Parse complex JSON object with GSON with changing content due to OOP - java

I get such a JSON from the server and want to parse it to my objects:
"product":{
"product_type":"assignment",
"id":717,
"product_profile":{
"title":"new Order from java",
"info":"Some special info",
"dtl_expl":true,
"special_info":""
}
}
Depend on "product_type" value I get different value of "product_profile" from server. The "product_profile" can be one of three types. I created class presentation for each of them. But question is that how organize correct parsing of JSON object to my Product class due to OOP principles? Should I create interface and implement it in each of my three classes, or I should create one parent class and extend it in my three classes to make it work right?
My classes structure. First of all Product class , object of which I should get as a result from json:
public class Product {
ProductAssignment prodAss;
ProductWriting prodWr;
ProductType returnState;
#SerializedName("id")
int id;
#SerializedName("product_type")
String product_type;
#SerializedName("product_profile")
ProductType product_profile;
public Product()
{}
public Product(int id, String product_type, ProductType product_profile)
{
this.id = id;
this.product_type = product_type;
this.product_profile = product_profile.returnObject(product_type);
}
public int getProductId()
{
return this.id;
}
public String getProductType()
{
return this.product_type;
}
public ProductType getProduct()
{
return product_profile.returnObject(product_type);
}
public void setProductId(int id)
{
this.id = id;
}
public void setProductTitle(String product_type)
{
this.product_type = product_type;
}
public void setProduct(ProductType product_profile)
{
this.product_profile = product_profile;
}
#Override
public String toString() {
return "id=" + id + " " + "title=" + product_type
+ " " + "profile=" + product_profile + "}";
}
}
Now parent class ProductType for two subclasses:
public class ProductType extends ProductType{
String product;
static ProductType productType;
static ProductAssignment productAssignment;
static ProductWriting productWriting;
IProductType component;
private ProductType returnState;
ProductAssignment prodAss;
ProductWriting prodWr;
public ProductType()
{
}
public ProductType(IProductType c)
{
component = c;
}
// implemented method of interface
#Override
public ProductType returnObject(String product_type)
{
System.out.println("ProductType");
if (product_type.equals("assignment"))
returnState = prodAss.returnObject(product_type);
else if (product_type.equals("writing"))
returnState = prodWr.returnObject(product_type);
System.out.println(returnState.getClass().getName());
return returnState;
}
}
One of the subclasses:
public class ProductWriting extends ProductType{
#SerializedName("id")
int id;
#SerializedName("title")
String title;
#SerializedName("pages_number")
int pages_number;
#SerializedName("number_of_references")
String number_of_references;
#SerializedName("dtl_expl")
boolean dtl_expl;
#SerializedName("info")
String info;
public ProductWriting()
{}
public ProductWriting(String title, String info, boolean dtl_expl,
int pages_number ,
int id,String number_of_references)
{
this.title = title;
this.info = info ;
this.dtl_expl = dtl_expl;
this.id = id;
this.pages_number = pages_number;
this.number_of_references = number_of_references;
}
public ProductWriting(IProductType c){
super(c);
}
// getters and setters
#Override
public ProductType returnObject(String res) {
System.out.println("Writing");
super.returnObject(res);
return new ProductWriting();
}
}
Another one :
public class ProductAssignment extends ProductType{
ProductAssignment thisObj;
#SerializedName("title")
String title;
#SerializedName("info")
String info;
#SerializedName("dtl_expl")
boolean dtl_expl;
#SerializedName("special_info")
String special_info;
#SerializedName("shoot_exclusive_video")
boolean shoot_exclusive_video;
#SerializedName("shoot_common_video")
boolean shoot_common_video;
public ProductAssignment()
{}
public ProductAssignment(String title, String info, boolean dtl_expl, String special_info,
boolean shoot_common_video, boolean shoot_exclusive_video)
{
this.title = title;
this.info = info ;
this.dtl_expl = dtl_expl;
this.special_info = special_info;
this.shoot_common_video = shoot_common_video;
this.shoot_exclusive_video =shoot_exclusive_video;
}
// getters and setters
#Override
public ProductType returnObject(String res) {
System.out.println("Assignment");
super.returnObject(res);
return new ProductAssignment();
}
#Override
public String toString()
{
return "title=" + title + "info " + "=" + info
+ " " + "profile=" + dtl_expl + "}";
}
}
Interface for binding my classes:
public interface IProductType
{
ProductType returnObject(String parse);
}
I tried to implement in this way, but it doesn't work for now with it.

Related

Android POJO class check if particular key contains value as Boolean or arraylist

I have JsonArraylist in which there are multiple jsonobjects.In one of jsonObject json key contains Boolean value and on other Jsonobject the same key contain ArrayList.
How to check in POJO class if key contains ArrayList or boolean value as i am getting error:
W/System.err: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BOOLEAN at line 1 column 1927 path $1.tags
The Json is:
My POJO class is :
public class Posts implements Serializable
String id;
String title;
boolean mIsBookmark;
ArrayList<WebTags>tags;
public ArrayList<WebTags> getTags() {
return tags;
}
public void setTags(ArrayList<WebTags> tags) {
this.tags = tags;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public boolean isBookmark() {
return mIsBookmark;
}
public void setBookmark(boolean mIsBookmark) {
this.mIsBookmark = mIsBookmark;
}
#Override
public String toString() {
return "Webapps_post{" +
"id='" + id + '\'' +
", title='" + title + '\'' +
", date='" + date + '\'' +
", tags='"+ tags+'\'' +
'}';
}
public class WebTags implements Serializable
{
String term_id;
String name;
public String getTerm_id() {
return term_id;
}
public void setTerm_id(String term_id) {
this.term_id = term_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString()
{
return "WebTags{"+
"term_id='" + term_id + '\'' +
", name='" + name + '\'' +
'}';
}}
}
The TypeAdapter is exactly what you are looking for. To summarize you can add a custom conversion logic for a user defined datatype such as a class and the Gson serializer/deserializer is smart enough to do it based on the return type of the conversion methods
An example for the usage can be found here
You would need to create a custom deserializer for class Posts like below:
class PostsDeserializer : JsonDeserializer<Posts> {
#Throws(JsonParseException::class)
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Posts {
val finalResult = Posts()
// manually set all elements (except 'tags') to finalResult object.
//...
// set tags element now
val tagsElement = json.asJsonObject.get("tags")
if(tagsElement?.isJsonArray == true) {
finalResult.tags = context.deserialize(tagsElement, WebTags::class.java)
} else {
finalResult.tags = emptyList()
}
return finalResult
}
}
The above code will tell the GSON library what to map when the tags field is an array or when the tags field is a boolean.

Superclass overriding Subclass with default values from constructor in Java

I have an assignment and my superclass default values always override the values I pass in the Test main method. In the debugger, i see the passing of the productNumber(1234) and productTitle("Daughter"), but then it's overridden with the default values. Any thoughts, i keep making minor changes, checking for changes, still the same results.
Product Superclass
public abstract class Product {
private int productNumber;
private String productTitle;
//Two constructors required
public Product(){
productNumber = 0;
productTitle = "";
}
public Product(int productNumber, String productTitle) {
this.productNumber = productNumber;
this.productTitle = productTitle;
}
public void setProductNumber(int productNumber) {
this.productNumber = productNumber;
}
public int getProductNumber() {
return productNumber;
}
public void setProductTitle(String productTitle) {
this.productTitle = productTitle;
}
public String getProductTitle() {
return productTitle;
}
//Override toString() required
#Override
public String toString() {
return productNumber + " " + productTitle;
}
// Required Product class declares abstract method with this signature: public String getDisplayText()
public abstract String getDisplayText();
//Override equals() required
#Override
public boolean equals(Object object) {
if (object instanceof Product) {
Product product2 = (Product) object;
if (productNumber == (product2.getProductNumber()) &&
productTitle.equals(product2.getProductTitle())){
return true;
}
}
return false;
}
}
Music Subclass extends Product Superclass
public class Music extends Product {
private String artist;
private String style;
private String medium;
public Music() {
super();
artist = "";
style = "";
medium = "";
}
public Music(int productNumber, String productTitle, String artist, String style, String medium) {
super();
this.artist = artist;
this.style = style;
this.medium = medium;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public String getStyle() {
return style;
}
public void setStyle(String style) {
this.style = style;
}
public String getMedium() {
return medium;
}
public void setMedium(String medium) {
this.medium = medium;
}
#Override
public String getDisplayText() {
return super.toString() + " by " + artist + " " + style + " " + medium;
}
#Override
public boolean equals(Object object){
if (object instanceof Music){
Music m = (Music) object;
if (artist.equals(m.getArtist()) &&
style.equals(m.getStyle()) &&
medium.equals(m.getMedium())){
return true;
}
}
return false;
}
}
Print String
public class Test {
public static void main(String[] args) {
// Expected result: 1234 Daughter by Pearljam Alternative online
Music music1 = new Music(1234,"Daughter", "Pearljam","Alternative","online");
System.out.println(music1.getDisplayText());
}
}
you are not passing values from subclass to your parentclass
instead of super() you need to do below -
super(productNumber,productTitle);
update needed in your code :-
public Music(int productNumber, String productTitle, String artist, String style, String medium) {
super(productNumber,productTitle);
this.artist = artist;
this.style = style;
this.medium = medium;
}
You need to pass productNumber and productTitle in the super(..., ...) call inside the Music constructor up to the parent class.
You need to invoke
super(productNumber, productTitle)
inside the Music constructor to pass the parameters to its parent.

join two table using hibernate

I have two table entity channel and channel_stats.I want to save data in tables using session.save().
channel_stats can contain duplicate entry with duplicate channel ID.
Can you please tell me how to do so using secondary table annotation in hibernate. or is there any other way? i tried with embedded and embedded annotation bit looks like its for same table
#Entity
#Table(name="channel_list")
public class Channel {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="channel_youtubeID")
private String channelYoutubeID;
#Column(name="channel_title")
private String channelTitle;
#Column(name="thumbnail_url")
private String thumbnailUrl;
#Column(name="active_bit")
private int activeBit;
#Embedded
private ChannelStats channelStats;
public Channel() {
}
public Channel(String channelYoutubeID, String channelTitle, String thumbnailUrl, int activeBit,
ChannelStats channelStats) {
super();
this.channelYoutubeID = channelYoutubeID;
this.channelTitle = channelTitle;
this.thumbnailUrl = thumbnailUrl;
this.activeBit = activeBit;
this.channelStats = channelStats;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getChannelYoutubeID() {
return channelYoutubeID;
}
public void setChannelYoutubeID(String channelYoutubeID) {
this.channelYoutubeID = channelYoutubeID;
}
public String getChannelTitle() {
return channelTitle;
}
public void setChannelTitle(String channelTitle) {
this.channelTitle = channelTitle;
}
public String getThumbnailUrl() {
return thumbnailUrl;
}
public void setThumbnailUrl(String thumbnailUrl) {
this.thumbnailUrl = thumbnailUrl;
}
public int getActiveBit() {
return activeBit;
}
public void setActiveBit(int activeBit) {
this.activeBit = activeBit;
}
public ChannelStats getChannelStats() {
return channelStats;
}
public void setChannelStats(ChannelStats channelStats) {
this.channelStats = channelStats;
}
#Override
public String toString() {
return "Channel [id=" + id + ", channelYoutubeID=" + channelYoutubeID + ", channelTitle=" + channelTitle
+ ", thumbnailUrl=" + thumbnailUrl + ", activeBit=" + activeBit + ", channelStats=" + channelStats
+ "]";
}
}
#Embeddable
#Table(name="channel_stats")
public class ChannelStats {
#Column(name="channelID")
private String channelID;
#Column(name="viewCount")
private long viewCount;
#Column(name="commentCount")
private long commentCount;
#Column(name="subscriberCount")
private long subscriberCount;
#Column(name="hiddenSubscriberCount")
private boolean hiddenSubscriberCount;
#Column(name="videoCount")
private long videoCount;
public ChannelStats() {
}
public ChannelStats(String channelID, long viewCount, long commentCount, long subscriberCount,
boolean hiddenSubscriberCount, long videoCount) {
super();
this.channelID = channelID;
this.viewCount = viewCount;
this.commentCount = commentCount;
this.subscriberCount = subscriberCount;
this.hiddenSubscriberCount = hiddenSubscriberCount;
this.videoCount = videoCount;
}
public String getChannelID() {
return channelID;
}
public void setChannelID(String channelID) {
this.channelID = channelID;
}
public long getViewCount() {
return viewCount;
}
public void setViewCount(long viewCount) {
this.viewCount = viewCount;
}
public long getCommentCount() {
return commentCount;
}
public void setCommentCount(long commentCount) {
this.commentCount = commentCount;
}
public long getSubscriberCount() {
return subscriberCount;
}
public void setSubscriberCount(long subscriberCount) {
this.subscriberCount = subscriberCount;
}
public boolean isHiddenSubscriberCount() {
return hiddenSubscriberCount;
}
public void setHiddenSubscriberCount(boolean hiddenSubscriberCount) {
this.hiddenSubscriberCount = hiddenSubscriberCount;
}
public long getVideoCount() {
return videoCount;
}
public void setVideoCount(long videoCount) {
this.videoCount = videoCount;
}
#Override
public String toString() {
return "ChannelStats [channelID=" + channelID + ", viewCount=" + viewCount + ", commentCount=" + commentCount
+ ", subscriberCount=" + subscriberCount + ", hiddenSubscriberCount=" + hiddenSubscriberCount
+ ", videoCount=" + videoCount + "]";
}
}
As I understand the question, #Embeddable is not what you want in this case. #Embeddable and #Embedded is used when you don't want a separate second table. Since you want a separate table to have the ChannelStat data, it seems like you are trying to create a #OneToMany relationship where one Channel object can have multiple ChannelStat objects.
So your Channel class should have
#OneToMany( mappedBy = "channel", cascade = CascadeType.ALL )
private List<ChannelStat> channelStat;
Instead of
#Embedded
private ChannelStats channelStats;
And your ChannelStat class should have
public class ChannelStats {
// Other variables and their getters and setters
#ManyToOne( cascade = CascadeType.ALL )
#JoinColumn( name = "id" )
private Channel channel;
}
Read here for more information.

java - Hibernate doesn't read object from database correctly

I am having some issues according Hibernate.
I have a more or less complex object structure that I want to save / load using the Hibernate EntityManager (version 4.3.5.Final). I managed to save it, but if I attempt to read the obejct, only the PK will be read. The EntityManager's find method returns null even with the correct PK so I am using its getReference method.
I still have troubles using the correct relationship (ManyToOne and such) so I most likely made a mistake there and I guess that is causing the problem.
Anyways.
My question is: How do i persist an object structure like this using Hibernate?
Here are the POJOs i am using:
EDIT: Updated the Code
CalculationList:
#Entity(name = "calculation")
public class CalculationList implements EntityList {
#Id
private Date created;
#OneToMany(mappedBy = "", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Product> products;
public CalculationList(Date created) {
this.created = created;
this.products = new LinkedList<>();
}
public CalculationList(Date created, List<Product> products) {
this.created = created;
this.products = products;
}
public CalculationList() {
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> entities) {
this.products = entities;
}
#Override
public String toString() {
return "CalculationList{" +
"created=" + created +
", products=" + products +
'}';
}
}
CalulatorEntity:
#Entity(name = "calculator_entity")
public class CalculatorEntity implements Serializable {
#Id
private int id;
private CalculatorEntityType type;
private String name;
private int number;
#ManyToOne(cascade = CascadeType.ALL)
private Product product;
public CalculatorEntity(CalculatorEntityType type) {
this.type = type;
}
protected CalculatorEntity() {
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public CalculatorEntityType getType() {
return type;
}
public void setType(CalculatorEntityType type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public enum CalculatorEntityType {
GAS_PUMP, DELIVERY_BILL;
}
#Override
public String toString() {
return "CalculatorEntity{" +
"id=" + id +
", type=" + type +
", name='" + name + '\'' +
", product=" + product +
", number=" + number +
'}';
}
}
Product:
#Entity(name = "product")
public class Product implements Serializable {
#Id
private int id;
private String name;
private ProductType type;
#OneToMany(mappedBy = "product", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<CalculatorEntity> entities;
public Product(String name, ProductType type) {
this.name = name;
this.type = type;
this.entities = new LinkedList<>();
}
/**
* JPA - Konstruktor
*/
public Product() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ProductType getType() {
return type;
}
public void setType(ProductType type) {
this.type = type;
}
public List<CalculatorEntity> getEntities() {
return entities;
}
public void setEntities(List<CalculatorEntity> entities) {
this.entities = entities;
}
#Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + '\'' +
", type=" + type +
", entities=" + entities +
'}';
}
public enum ProductType {
FUEL("Treibstoff"), OIL("Öl"), OTHER("Verschiedenes");
private String name;
private ProductType(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
}
You are using the #OneToMany mapping with the wrong entity, instead of mapping Product class you are mapping CalculationList class, move the following configuration:
#OneToMany(mappedBy = "product", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<CalculatorEntity> entities;
to the Product class.

Creating an object and calling it

this is my current code to store rooms(it compiles fine) but in the UML there is a variable called addEquipment and there is also another class called Equipment to be defined. I'm having trouble wrapping my head around what I'm supposed to do with this. Am I supposed to create and call an object called Equipment? what goes in addEquipment?
public class Room {
//begin variable listing
private String name;
private int id;
private int capacity;
private String equipmentList;
//begins get methods for variables
public String getName(){
return name;
}
public int getID(){
return id;
}
public int getCapacity(){
return capacity;
}
public String getEquipmentList(){
return equipmentList;
}
// Set the variables
public void setName(String aName){
name=aName;
}
public void setID(int anID){
id=anID;
}
public void setCapacity(int aCapacity){
capacity=aCapacity;
}
public void setEquipmentList(String anEquipmentList){
equipmentList=anEquipmentList;
}
public String addEquipment(String newEquipment, String currentEquipment){
}
//Create room object
public Room(int capacity, String equipmentList) {
setCapacity(capacity);
setEquipmentList(equipmentList);
}
//Convert variables to string version of room
public String toString(){
return "Room "+name+", capacity: "+capacity+", equipment: "+getEquipmentList();
}
}
You can create a new class Equipment and modify your attribute equipmentList to be a List:
public class Equipment {
private String name;
public Equipment(String name) {
this.name = name;
}
}
public class Room {
//begin variable listing
private String name;
private int id;
private int capacity;
private List<Equipment> equipmentList = new ArrayList<Equipment>();
//begins get methods for variables
public String getName(){
return name;
}
public int getID(){
return id;
}
public int getCapacity(){
return capacity;
}
public List<Equipment> getEquipmentList(){
return equipmentList;
}
// Set the variables
public void setName(String aName){
name=aName;
}
public void setID(int anID){
id=anID;
}
public void setCapacity(int aCapacity){
capacity=aCapacity;
}
public void setEquipmentList(List<Equipment> anEquipmentList){
equipmentList=anEquipmentList;
}
public String addEquipment(String newEquipment, String currentEquipment){
Equipment oneEquipment = new Equipment(newEquipment);
equipmentList.add(oneEquipment);
}
//Create room object
public Room() {
setCapacity(capacity);
setEquipmentList(equipmentList);
}
//Convert variables to string version of room
public String toString(){
String capacity=String.valueOf(getCapacity());
String room = "Room "+name+", capacity: "+capacity+", equipment: "+getEquipmentList();
return room;
}
}
In the method addEquipment, you can create a new Equipment and add it to equipmentList, like code above.
An Equipment class could be anything. Lets assume the "Equipment"-class has a String called "name" as it's attribute
public class Equipment {
String name;
public Equipment( String name) {
this.name = name;
}
public String getName() {
return this.name
}
}
When you extend your Room class by the requested "addEquipment" method, you can do something like this.
public class Room {
... // Your code
private int equipmentIndex = 0;
private Equipment[] equipment = new Equipment[10]; // hold 10 Equipment objects
public void addEquipment( Equipment eq ) {
if ( equipmentIndex < 10 ) {
equipment[ equipmentIndex ] = eq;
equipmentIndex++;
System.out.println("Added new equipment: " + eq.getName());
} else {
System.out.println("The equipment " + eq.getName() + " was not added (array is full)");
}
}
}
Now when you call
room.addEquipment( new Equipment("Chair") );
on your previously initialized object of the Room-class, you will get
"Added new equipment: Chair"
Hope this helps a bit.
PS: The code is untestet (maybe there hides a syntax error somewhere)

Categories

Resources