GSON one to one relationship - json

I want to know what should be the JSON structure for Gson library to work with one to one relationship (also know as belongsTo).
This is my model
public class Course {
private int id;
private String name;
private Teacher teacher;
//...setters and getters
}
public class Teacher {
private int id;
private String name;
private String lastName;
//...setters and getters
}
until now, my JSON format for filling a Course using gson.fromJSON(string,Course.class) is the following:
{
"id":1,
"name":"Math"
}
how can I also fill a Teacher ?

If your JSON was structured like this, I believe GSON should handle it properly.
{
"id":1,
"name":"Math",
"teacher": {
"id": 2,
"name": "John",
"lastName": "Doe"
}
}

Related

Validate 2 Json Fields for Not Null at the same time

I have below JSON . At any point of time only one of the field "car" or "bike" can be null .Not both at the same time.How can I validate json using Jackson annotations.
All the fields in JSON are mandatory
{
"name": "John",
"age": 30,
"car": "Toyota",
"bike": "Honda"
}
My Java Pojo Objects
public class Example
{
#JsonProperty("name")
public String name;
#JsonProperty("age")
public Integer age;
#JsonProperty("car")
public String car;
#JsonProperty("bike")
public String bike;
Depending what you want, you can use #NotBlank from javax.validation.constraints.NotBlank;
public class Example
{
#NotBlank(message = "This field cannot be blank")
#JsonProperty("name")
public String name;
#JsonProperty("age")
public Integer age;
#JsonProperty("car")
public String car;
#JsonProperty("bike")
public String bike;
}
You can also try #NotNull or #NotEmpty from same package. They have some differences, see what best fit on your case.

Mapping JSON Array to Spring Hibernate Database (H2)

Hi I'm trying to map a JSON to databse table in SprinBoot.
This is my #Entity:
#Data
#AllArgsConstructor
#Entity
public class User {
#Id
#GeneratedValue( strategy = GenerationType.AUTO )
private Long id;
private String name;
private String tagline;
private String first_brewed;
#Column(length=700)
private String description;
private String image_url;
private Long ibu;
private String[] food_pairing;
public User() {}
}
And JSON looks that:
[
{
"id": 1,
"name": "Buzz",
"tagline": "A Real Bitter Experience.",
"first_brewed": "09/2007",
"description": "A light, crisp and bitter IPA brewed with English and American hops. A small batch brewed only once.",
"image_url": "https://images.punkapi.com/v2/keg.png",
"ibu": 60,
"food_pairing": [
"Spicy chicken tikka masala",
"Grilled chicken quesadilla",
"Caramel toffee cake"
]
}
]
I want to save this in to the H2 database.
Got only 1 column in the database with string of letters and numbers
My question is: How to change
private String[] food_pairing;
to show all food_pairings as a separate columns in the database?
(If I have an object in JSON i can do that in the #Entity:
#Embedded private Address address;
And then in other class:
#Embeddable public class Address {
private String street;
private String suite;
}
And I have a automatic created columns in my database. I want to do the same but not with an object in JSON only with an Array of Strings in JSON.
If I understand your requirement, you want to persist this array private String[] foodPairing; in one column. If so, you can proceed like below :
public class User {
....
#Transient
private String[] foodPairing;
#Column(name="food_pairing")
private String food_Pairing;
}
And before persisting your entity you can do this:
user.setFood_Paring(user.getFoodPairing().toString());
Then persist.
EDIT:
In case where you want each String in a one column, you can add 3 fields in your entity like this:
public class User {
....
#Transient
private String[] foodPairing;
#JsonIgnore
#Column(name="food_pairing1")
private String foodPairing1;
#JsonIgnore
#Column(name="food_pairing2")
private String foodPairing2;
#JsonIgnore
#Column(name="food_pairing3")
private String foodPairing3;
}
And when you persist:
user.setFoodParing1(user.getFoodPairing()[0]); //etc...

How to combine #JsonView with #JsonProperty?

I have a DTO class that should serve json via a spring-mvc #RestController.
I want to provide different version/views on the same object. Especially, there are fields that are only used in VERSION_1 of the api, and some only in VERSION_2.
Problem: I could add #JsonView for this, but my goal is also to rename those fields. Some fields should actually replace the same name from previous versions.
Example:
public class Person {
#JsonView(View.Version_1.class)
#JsonProperty("name")
private String name; //eg only the firstname
#JsonView(View.Version_2.class)
#JsonProperty("name")
private NameDTO namedto; //now changing to first+last name
static class NameDTO {
private String firstname;
private String lastname;
}
}
#RestController
public class MyServlet {
#GetMapping("/person/{id}")
#JsonView(View.Version_1.class)
public PersonDTO person1(int id) {
//...
}
#GetMapping("/person_new/{id}")
#JsonView(View.Version_2.class)
public PersonDTO person2(int id) {
//...
}
}
So, depending on the view/version, you would get the same json field firstname, but with different content.
In this example, using V1 would give:
{"name": "john"}
Whereas using V2 should result in:
{"name": {"firstname": "john", "lastname": "doe"}}
BUT not with he code above, as jackson complains:
com.fasterxml.jackson.databind.JsonMappingException: Conflicting
getter definitions for property "name".
Is that possible at all?
I found a way using:
https://github.com/jonpeterson/spring-webmvc-model-versioning
Basic idea is to add a custom VersionedModelConverter that is applied on #VersionedModelConverter annotated webservice response classes.
#Configuration
#Import(VersionedModelResponseBodyAdvice.class)
public class SpringMvcVersioningConfiguration {
//register in jackson. spring-boot automatically registers any module beans
#Bean
public Model versioningModel() {
return new VersioningModule();
}
}
#GetMapping
#VersionedResponseBody(defaultVersion = "2.0")
public Person person() {
}
#JsonVersionedModel(currentVersion = "3.0" toPastConverterClass = PersonConverter.class)
public class Person {
}
public class PersonConverter implements VersionedModelConverter {
#Override
public ObjectNode convert(ObjectNode modelData, String modelVersion, String targetModelVersion, JsonNodeFactory nodeFactory) {
Double modelv = Double.valueOf(modelVersion);
Double targetv = Double.valueOf(targetVersion);
//todo if-else based on model version
Object node = modelData.remove("fieldname");
//node.change...
modelData.set("fieldname_renamed", node);
}
}

JsonArray and Gson

The JSON library I'm using is Gson. I'm having difficulty formulating a functioning data type to represent the following JSON string:
{
"latestoffers": [
{
"id": "4qXleunwNMCKi8M0q0CuMa",
"price": "534.99",
"firstrecorded_at": 1377808800,
"lastrecorded_at": 1382862800,
"seller": "Newegg",
"availability": "In stock. [BBX: Buy Box]",
"currency": "USD"
},
{
"id": "4xTIQAPySG68IS0CGyOuyO",
"price": "582.41",
"firstrecorded_at": 1380725000,
"lastrecorded_at": 1382862800,
"seller": "Beach Audio",
"currency": "USD"
},
{
"id": "5nW67R2V4CwmE8cwaWsawe",
"price": "578.04",
"firstrecorded_at": 1379524200,
"lastrecorded_at": 1379998900,
"seller": "Beach Audio",
"currency": "USD"
}
],
"offers_count": 6,
"name": "newegg.com",
"recentoffers_count": 2,
"sku": "N82E16834216463",
"url": "http://www.newegg.com/Product/Product.aspx?Item=N82E16834216463"
}
My data class (so far) is as follows, it's the method getOfferData() that I don't how to complete. I'm also not certain whether JsonArray is the appropriate JSON element to be using?
static class LatestOffers {
Integer offers_count;
String name;
Integer recentoffers_count;
String sku;
String url;
java.util.List<JsonArray> getOfferData() {
List<JsonArray> list = new ArrayList<JsonArray>();
// how do I get parse the 'id', 'price', 'firstrecorded_at' etc. to add them to the ArrayList?
return list;
}
Integer getOffers_count() {
return offers_count;
}
String getName() {
return name;
}
Integer getRecentoffers_count() {
return recentoffers_count;
}
String getSku() {
return sku;
}
String getUrl() {
return url;
}
}
Any assistance, please? Thank you.
EDIT
Turns out I was unnecessarily complicating things, this works as intended:
static class LatestOffers {
List<Offer> latestoffers;
List<Offer> getOffer() {
return latestoffers;
}
}
static class Offer {
private String id;
private String price;
private long firstrecorded_at;
private long lastrecorded_at;
private String seller;
private String availability;
private String currency;
String getId() {
return id;
}
String getPrice() {
return price;
}
long getFirstrecorded_at() {
return firstrecorded_at;
}
long getLastrecorded_at() {
return lastrecorded_at;
}
String getSeller() {
return seller;
}
String getAvailability() {
return availability;
}
String getCurrency() {
return currency;
}
}
Thank you to all who answered, I'm accepting the answer of user2762451 as (s)he was the first to suggest the use of another class for the Offer data.
I'd advise you to make new POJO for object in array.
class Offer {
private String id;
private String price;
private long firstRecordedAt;
private long lastRecordedAt;
private String seller;
private String availability;
private String currency;
}
And your LatestOffers class can have a List<Offer> offers; and the method getOfferData() should return List<Offer>.
Basically, the following:
static class LatestOfferDetail {
private int offersCount;
private String name;
private int recentOffersCount;
private String sku;
private String url;
private List<Offer> latestOffers = new ArrayList<Offer>();
//other getters and setters
public List<Offer> getLatestOffers() {
return latestOffers;
}
}
Also, you seem to be following multiple naming conventions in the same piece of code and JSON. With JAVA, it's advisable to follow CamelCaseNaming. I've updated answer to reflect those.
Also, your getter method for latestOffers has a name different from convention. It's advisable to name it like get{FieldName}. I've updated answer to reflect that.
Create another POJO contain all parameter use in array like below :
public class MyOffer
{
private String id;
private double price;
private long firstrecorded_at;
private long lastrecorded_at;
private String seller;
private String availability;
private String currency;
//your getter and setter methods here.
}
Include List of above pojo in your class LatestOffers :
List<MyOffer> latestoffers = new ArrayList<MyOffer>();
your class LatestOffers look like this
static class LatestOffers
{
Integer offers_count;
String name;
Integer recentoffers_count;
String sku;
String url;
List<MyOffer> latestoffers = new ArrayList<MyOffer>();
//getter and setter method
}
Main Class for Test:
public static void main(String[] args) {
LatestOffers lso = new LatestOffers();
lso.setName("N82E16834216463");
lso.setOffers_count(6);
lso.setRecentoffers_count(2);
lso.setSku("N82E16834216463");
lso.setUrl("http://www.newegg.com/Product/Product.aspx?Item=N82E16834216463");
MyOffer offer = null;
List<MyOffer> list = new ArrayList<MyOffer>();
for(int i=0;i<2;i++){
offer = new MyOffer();
offer.setAvailability("In stock. [BBX: Buy Box]");
offer.setCurrency("USD");
offer.setFirstrecorded_at(1377808800);
offer.setId("4qXleunwNMCKi8M0q0CuMa");
offer.setLastrecorded_at(1382862800);
offer.setPrice(534.99);
offer.setSeller("Newegg");
list.add(offer);
}
lso.setLatestoffers(list);
Gson gson = new Gson();
String json = gson.toJson(lso);
System.out.println(json);
}
Output :
{
"offers_count": 6,
"name": "N82E16834216463",
"recentoffers_count": 2,
"sku": "N82E16834216463",
"url": "http://www.newegg.com/Product/Product.aspx?Item=N82E16834216463",
"latestoffers": [
{
"id": "4qXleunwNMCKi8M0q0CuMa",
"price": 534.99,
"firstrecorded_at": 1377808800,
"lastrecorded_at": 1382862800,
"seller": "Newegg",
"availability": "In stock. [BBX: Buy Box]",
"currency": "USD"
},
{
"id": "4qXleunwNMCKi8M0q0CuMa",
"price": 534.99,
"firstrecorded_at": 1377808800,
"lastrecorded_at": 1382862800,
"seller": "Newegg",
"availability": "In stock. [BBX: Buy Box]",
"currency": "USD"
}
]
}
no need to define getOfferData() method just create list of MyOffer class and set that list into latestoffers list define in your class LatestOffers. It will serialize your list into JsonArray when you convert your POJO into JSON String.

Parsing Json with Gson gives nullfield in object

i got JSON that have object inside
{
"status": "OK",
"info": null,
"data": {
"product": {
"productId": "1",
"productName": "Oreo"
}
}
i parse with
ProductResponse.java
public class ProductResponse {
#SerializedName("status")
public String status;
#SerializedName("info")
public String info;
#SerializedName("data")
public Product data;
}
Product.java
public class Product {
#SerializedName("productId")
public String productId;
#SerializedName("productName")
public String productName;
}
and in reponse i get status = "OK", info = null, and data that is product with nullfields
You've defined ProductResponse#data as a String. In the JSON, it's clearly not a string, it's an object. I know nothing about GSON, but surely that's the problem... Now you've changed the question so that data is defined as Product.
But data isn't a Product, it's an object that has a product property.
It seems like you should have
public class ProductResponseData {
#SerializeName("product")
public Product product;
}
and then change ProductResponse's data to be:
#SerializedName("data")
public ProductResponseData data;