object convert to json how to modify the property key? - json

i have a json like
"weatherInfo":{
"city":"北京",
"publishDate":"2014年3月4日",
"week":"星期二",
"tempRange":"8℃~-3℃",
"feelTemp":"10",
"time":"16:05",
"temp":"11",
"WD":"北风",
"WS":"2级",
"SD":"27%",
"weather1":"晴"
}
and my class is
public class WeatherVO implements Serializable{
private static final long serialVersionUID = 2348480036959754071L;
#JsonProperty(value="weatherinfo")
private WeatherInfoVO weatherInfoVO;
#JsonIgnoreProperties(ignoreUnknown=true)
public class WeatherInfoVO{
//城市
#JsonProperty(value="city")
private String city;
//发布日期
private String publishDate;
//发布时间
#JsonProperty(value="time")
private String publishTime;
//星期
private String week;
//温度范围
private String tempRange;
//当前时刻温度
#JsonProperty(value="temp")
private String currentTemp;
//风向
#JsonProperty(value="WD")
private String windDirection;
//风力
#JsonProperty(value="WS")
private String windForce;
//当前时刻湿度
#JsonProperty(value="SD")
private String currentHumidity;
//体感温度
private String feelTemp;
//天气描述
private String weatherDesc;
}
}
i want to convert json to object like:
WeatherVO weatherVO = objectMapper.readValue (jsonString, WeatherVO.class);
and i want to return json use org.springframework.http.converter.json.MappingJacksonHttpMessageConverter class
and the return json is
"weatherInfo":{
"city":"北京",
"publishDate":"2014年3月4日",
"week":"星期二",
"tempRange":"8℃~-3℃",
"feelTemp":"10",
"time":"16:05",
"temp":"11",
"WD":"北风",
"WS":"2级",
"SD":"27%",
"weather1":"晴"
}
but i want to return like
"weatherInfo":{
"city":"北京",
"publishDate":"2014年3月4日",
"week":"星期二",
"tempRange":"8℃~-3℃",
"feelTemp":"10",
"publishTime":"16:05",
"currentTemp":"11",
"windDirection":"北风",
"windForce":"2级",
"currentHumidity":"27%",
"weather":"晴"
}
how can i do that?
thanks for your any suggestion and help.

You can achieve this by marking the getter of the field by #JsonIgnore then create another method that get the field and mark it as #JsonProperty.
My advice is to rename first your fields to avoid confusion. I renamed it like the json you have. So for example.
public class WeatherInfoVO{
private String city;
private String publishDate;
private String week;
private String tempRange;
private String feelTemp;
private String time;
private String temp;
private String WD;
private String WS;
private String SD;
private String weather1;
//getters and setters
}
then in you setters method mark the appropriate #JsonProperty.
#JsonProperty(value="time")
public void setTime(String time) {
this.temp = temp;
}
#JsonProperty(value="temp")
public void setTemp(String temp) {
this.temp = temp;
}
#JsonProperty(value="WD")
public void setWD(String WD) {
this.WD = WD;
}
#JsonProperty(value="WS")
public void setWS(String WS) {
this.WS = WS;
}
#JsonProperty(value="SD")
public void setSD(String SD) {
this.SD = SD;
}
#JsonProperty(value="weather1")
public void setWeather1(String weather1) {
this.weather1 = weather1;
}
//other setters here
and in your getters, make sure to add #JsonIgnore to the fields you want to rename. Since you declare it as #JsonIgnore, you need to create another getter and mark it as #JsonProperty. Do it only to the fields you are going to rename, in your case the fields are time, temp, WD, WS, SD and weather1 only. Here's an example.
#JsonIgnore
public void getTime(){
return time;
}
#JsonProperty(value="publishTime")
public void getPublishTime(){
return time;
}
#JsonIgnore
public void getTemp(){
return temp;
}
#JsonProperty(value="currentTemp")
public void getCurrentTemp(){
return temp;
}
#JsonIgnore
public void getWD(){
return WD;
}
#JsonProperty(value="windDirection")
public void getWindDirection(){
return WD;
}
#JsonIgnore
public void getWS(){
return WS;
}
#JsonProperty(value="windForce")
public void getWindForce(){
return WS;
}
#JsonIgnore
public void getSD(){
return SD;
}
#JsonProperty(value="currentHumidity")
public void getCurrentHumidity(){
return SD;
}
#JsonIgnore
public void getWeather1(){
return weather1;
}
#JsonProperty(value="weather")
public void getWeather(){
return weather1;
}

Related

JAVA Spring boot how to post arraylist in Postman

I am trying to save some books via request but I am getting errors. How do I exactly do this? This is the model
#Entity
public class Reservation {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String user;
private int period;
#OneToMany
private List<Books> books;
public static String error () {
return "Input error";
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public int getPeriod() { return period;}
public void setPeriod(int period) {this.period = period;}
public List<Books> getBooks() { return books;}
public int getId() {return id;}
public void setId(int id) {this.id = id;}
#Entity
public class Books implements Serializable {
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY )
private int id;
private String name;
}
}
Controller:
#PostMapping("/reserveBook")
public String reserveBook(#RequestBody Reservation reservation)
{
if (reservation.getPeriod() > 2)
return Book.error();
else{
reserveRepo.save(reservation);
return "success";
}
}
Tried json like this
{
"user": "Jason",
"books":[{"name": "Wonders"}, {"name": "Good classics"}],
"period": 2
}
What exact error you are getting? Can you try to make your inner class static? Like
public static class Books implements Serializable

SpringBoot JSON not deserializing into my request model

I am using SpringBoot and trying to deserialize JSON like:
{
"userId": "Dave",
"queryResults": {
"id": "ABC",
"carData": {.....},
"carId": "Honda",
"status": 0,
"model": "X"
}
}
, into MyRequestModel clas:
public class MyRequestModel {
private String userId;
private String: queryResults;
}
, that is received as #RequestBody parameter in my #PostMapping method that looks like:
#PostMapping
public String postDate(#RequestBody MyRequestModel data) {
...
return "posted";
}
The above queryResults field is supposed to be stored as a CLOB in a database.
Problem I am having is that if I send this JSON to hit my endpoint (PostMapping) method, it cannot deserialize it into MyRequestModel and I get this error:
Cannot deserialize instance of java.lang.String out of START_OBJECT token
at [Source: (PushbackInputStream); line: 3, column: 18] (through reference chain: MyRequestModel["queryResults"])]
I guess the real answer to your question is: if you NEED the queryResults property to be a String, then implement a custom deserializer.
If not, then, use one of the alternatives that Jonatan and Montaser proposed in the other answers.
Implementing a custom deserializer within Spring Boot is fairly straightforward, since Jackson is its default serializer / deserializer and it provides a easy way to write our own deserializer.
First, create a class that implements the StdDeserializer<T>:
MyRequestModelDeserializer.java
public class MyRequestModelDeserializer extends StdDeserializer<MyRequestModel> {
public MyRequestModelDeserializer() {
this(null);
}
public MyRequestModelDeserializer(Class<?> vc) {
super(vc);
}
#Override
public MyRequestModel deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = p.getCodec().readTree(p);
String userId = node.get("userId").asText();
String queryResults = node.get("queryResults").toString();
MyRequestModel model = new MyRequestModel();
model.setQueryResults(queryResults);
model.setUserId(userId);
return model;
}
}
Second, mark your class to be deserialized using your custom deserializer by using the #JsonDeserialize annotation:
MyRequestModel.java
#JsonDeserialize(using = MyRequestModelDeserializer.class)
public class MyRequestModel {
private String userId;
private String queryResults;
}
It's done.
queryResults is a String on Java side but it is an Object on JSON side.
You will be able to deserialize it if you send it in as a String:
{
"userId": "Dave",
"queryResults": "foo"
}
or if you create classes that maps to the fields:
public class MyRequestModel {
private String userId;
private QueryResults queryResults;
}
public class QueryResults {
private String id;
private CarData carData;
private String carId;
private Integer status;
private String model;
}
or if you serialize it into something generic (not recommended):
public class MyRequestModel {
private String userId;
private Object queryResults;
}
public class MyRequestModel {
private String userId;
private Map<String, Object> queryResults;
}
public class MyRequestModel {
private String userId;
private JsonNode queryResults;
}
You have two options to deserialize this request:-
change the type of queryResults to Map<String, Object>, it will accepts everything as an object of key and value. (Not recommended)
public class MyRequestModel {
private String userId;
private Map<String, Object> queryResults;
}
You have to create a class that wraps the results of queryResults as an object.
class QueryResult {
private String id;
private Map<String, Object> carData;
private String carId;
private Integer status;
private String model;
public QueryResult() {}
public QueryResult(String id, Map<String, Object> carData, String carId, Integer status, String model) {
this.id = id;
this.carData = carData;
this.carId = carId;
this.status = status;
this.model = model;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Map<String, Object> getCarData() {
return carData;
}
public void setCarData(Map<String, Object> carData) {
this.carData = carData;
}
public String getCarId() {
return carId;
}
public void setCarId(String carId) {
this.carId = carId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
}
and make the type of queryResult as shown:-
public class MyRequestModel {
private String userId;
private QueryResult queryResults;
}

JSON unmarshalling to POJO and inserting

I would like to unmarshal a json string to a pojo class.
I am reading it from an existing url:
https://builds.apache.org/job/Accumulo-1.5/api/json
I am using apache camel to unmarshal the url
#Component
public class RouteBuilder extends SpringRouteBuilder {
private Logger logger = LoggerFactory.getLogger(RouteBuilder.class);
#Override
public void configure() throws Exception {
logger.info("Configuring route");
//Properties die hij niet vindt in de klasse negeren
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
DataFormat reportFormat = new JacksonDataFormat(objectMapper, HealthReport.class);
from("timer://foo?fixedRate=true&delay=0&period=2000&repeatCount=1")
.routeId("accumoloToJsonRoute")
.setHeader(Exchange.HTTP_METHOD, constant("GET"))
.to("https://builds.apache.org:443/job/Accumulo-1.5/api/json")
.convertBodyTo(String.class)
.unmarshal(reportFormat) //instance van Build
.log(LoggingLevel.DEBUG, "be.kdg.teamf", "Project: ${body}")
.to("hibernate:be.kdg.teamf.model.HealthReport");
}
}
So far so good. I would like to only insert the 'healthReport' node using hibernate annotations.
#XmlRootElement(name = "healthReport")
#JsonRootName(value = "healthReport")
#Entity(name = "healthreport")
public class HealthReport implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int Id;
#Column
#JsonProperty("description")
private String description;
#Column
#JsonProperty("iconUrl")
private String iconUrl;
#Column
#JsonProperty("score")
private int score;
public HealthReport() {
}
public HealthReport(int score, String iconUrl, String description) {
this.score = score;
this.iconUrl = iconUrl;
this.description = description;
}
public String getDescription() {
return description;
}
public String getIconUrl() {
return iconUrl;
}
public int getId() {
return Id;
}
public int getScore() {
return score;
}
public void setDescription(String description) {
this.description = description;
}
public void setIconUrl(String iconUrl) {
this.iconUrl = iconUrl;
}
public void setId(int id) {
Id = id;
}
public void setScore(int score) {
this.score = score;
}
}
This is where the problem is. It does not recognize the annotations
and only null values are inserted in my database
#XmlRootElement(name = "healthReport")
#JsonRootName(value = "healthReport")
Does anybody know how to fix this?
Thanks
Fixed it using a Processor for my Route
public class HealthReportProcessor implements Processor {
#Autowired
private ConfigurationService configurationService;
#Override
public void process(Exchange exchange) throws Exception {
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(exchange.getIn().getBody().toString());
ArrayNode report = (ArrayNode) root.get("healthReport");
int configId = configurationService.findJenkinsConfigurationByName(root.get("displayName").asText()).getId();
for (JsonNode node : report) {
JsonObject obj = new JsonObject();
obj.addProperty("description", node.get("description").asText());
obj.addProperty("iconUrl", node.get("iconUrl").asText());
obj.addProperty("score", node.get("score").asInt());
obj.addProperty("jenkinsConfig", configId);
exchange.getIn().setBody(obj.toString());
}
}
}
It is working but I think there is a better solution.
If you have a better solution please let me know ;)
Can you try this,
from("timer://foo?fixedRate=true&delay=0&period=2000&repeatCount=1")
.routeId("accumoloToJsonRoute")
.setHeader(Exchange.HTTP_METHOD,constant("GET"))
.to("https://builds.apache.org:443/job/Accumulo-1.5/apijson")
.unmarshal().json(JsonLibrary.Jackson, HealthReport.class)
And make sure the response params match the POJO fields.
Let me know if it works.

How to design database tables efficiently in Mysql

I have the following pojo
public class Like {
private Long commentId;
private Collection<Long> accountIds;
}
public class Comment {
private Long personId;
private Long pageId;
private Long Id;
private String text;
private Like like;
private LocalDate commentDate;
}
public class Page {
private Long Id;
private Long textId;
private Collection<Comment> comments;
private LocalTime postingDate;
private ViewType type;
private String mediaUrl;
private Collection<Long> openAccountIds;
private Like like;
}
public class Text{
private Long accountId;
private Long Id;
private String name;
private LocalTime firstPostedTime;
private LocalTime lastPostedTime;
private ViewType type;
private Collection<Page> pages;
private Like like;
private String description;
private Collection<Long> openAccountIds;
}
Now i have my text repository as follows:
public interface TextRepository {
Collection<Text> getAllTexts(Long accountId);
Diary getText(Long TextId);
Page getPage(Long pageId);
Comment getComment(Long commentId);
void addPageToText(Long TextId , Page page);
void addCommentToPage(Long pageId , Comment comment);
void updateText(Text text);
void deletePage(Long pageId);
void deleteComment(Long commentId);
void updateLikeToText(Long textIds);
void updateLikeToPage(Long pageId);
void updateLikeToComment(Long commentId);
}
I am a new bie to mysql. I wanted to know how to efficiently create mysql tables so i can retrieve the data in less possible time. Also if my pojo's contains any flaw in structure go ahead to change them or provide suggestions.
Here are some suggestions for the object model to consider (see comments),
// Specifying all the fields as private will not allow
// any other class to use the data!
public class Account
{
public String name;
public String location;
}
public class Text
{
public Collection<Account> likedBy;
public Collection<Account> openAccounts;
public Collection<Page> pages;
public Account postedBy;
public String name; // Not sure what this field represents...
public LocalTime firstPostedTime;
public LocalTime lastPostedTime;
public ViewType type;
public String description;
// Consider using get/set methods for collections,
// so as to expose only minimal required information
// public like(Account account)
// {
// likedBy.add(account);
// }
//
// public dislike(Account account)
// {
// likedBy.remove(account);
// }
}
public class Page
{
public Collection<Comment> comments;
public LocalTime postingDate;
public ViewType type;
public String mediaUrl;
public Collection<Account> openAccounts;
public Collection<Account> likedBy;
// public addComment(Comment comment)
// {
// ...
// Update posting date
// }
//
// public addOpenAccount(Account account)
// {
// ...
// }
}
public class Comment
{
public Account postedBy;
public String text;
public Collection<Account> likedBy;
public LocalDate commentDate;
}
The next step would be to construct an entity-relationship diagram. The primary keys and foreign keys (xxxId) are introduced while normalizing the schema.
The schema could look like this,
Account [id, name, location]
ViewType [id, description]
Comment [id, posted_by_account_id, text, postedDate]
CommentLikes [comment_id, account_id]
Text [id, account_id, name, firstPostedTime, lastPostedTime, type_Id, description]
TextAccounts [text_id, account_id]
TextLikes [text_id, account_id]
TextPages [text_id, page_id]
Page [id, mediaUrl, type_id, postingDate]
PageLikes [page_id, account_id]
PageComments [page_id, comment_id]
PageAccounts [page_id, account_id]

MOXy. generate JSON, doesn't contain reference class

I used Eclipselink MOXy to convert my POJO(using JPA) to json. and it's work.
but i have one problem. I have pojo class MAccount contain many to one relation to class MProduct,. when I convert to json, result show that class MAccount not in class MProduct.
here my class MAccount implementation:
#XmlRootElement
#Entity
#Table(name="m_account")
public class MAccount extends BaseObject implements Serializable {
private static final long serialVersionUID = UUID.randomUUID().getMostSignificantBits();
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#XmlID
private Long id;
#Column(name="account_id")
private String accountId;
#Column(name="card_number")
private String cardNumber;
//bi-directional many-to-one association to Product
#ManyToOne
#JoinColumn(name="m_product_id")
#XmlIDREF
private MProduct mProduct;
public MCustomerAccount() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getAccountId() {
return this.accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public MProduct getMProduct() {
return this.mProduct;
}
public void setMProduct(MProduct mProduct) {
this.mProduct = mProduct;
}
// Imlement base object method
...
}
here my class MProduct implementation:
#XmlRootElement
#Entity
#Table(name="m_product")
public class MProduct extends BaseObject implements Serializable {
private static final long serialVersionUID = UUID.randomUUID().getMostSignificantBits();
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#XmlID
private Long id;
#Column(name="product_code")
private String productCode;
#Column(name="product_name")
private String productName;
//bi-directional many-to-one association to MAccount
#OneToMany(mappedBy="mProduct")
#XmlInverseReference(mappedBy="mProduct")
private Set<MAccount> mAccountList;
public MProduct() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getProductCode() {
return this.productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return this.productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Set<MAccount> getMAccountList() {
return this.mAccountList;
}
public void setMAccountList(Set<MAccount> mAccountList) {
this.mAccountList = mAccountList;
}
// Imlement base object method
...
}
And generate JSON from MAccount class
{"MAccount":[
{"#type":"mAccount","id":"6","accountId":"05866039901"},
{"#type":"mAccount","id":"7","accountId":"25600036290"}]
}
there is no MProduct in there, the correct json result should be like below
{"MAccount":[
{"#type":"mAccount","id":6,"accountId":"05866039901","MProduct":{"#type":"mProduct","productCode":"T01","productName":"Book"}},
{"#type":"mAccount","id":7,"accountId":"25600036290","MProduct":{"#type":"mProduct","productCode":"T02","productName":"Pen"}}]
}
Is Anyone know how to solve this problem
Thank's b4
Because you are annotating the field, there is a chance that JPA has not populated that field yet due to lazy loading. If you annotate the property (get/set) instead do you still see this behaviour?
For more information on #XmlInverseReference see:
http://bdoughan.blogspot.com/2010/07/jpa-entities-to-xml-bidirectional.html