Java - Extract array String from JSON and convert to JSON format - java

I have a JSON String as below:
"{ \"password\":\"des123\",\"ROU_DATA\":[{\"FORM_RECEIVING_TIME\":\"12:00:00\",\"REMARKS\":\"Redemption of Unit\"}, {\"FORM_RECEIVING_TIME\":\"13:00:00\",\"REMARKS\":\"sALE of Unit\"}] }";
Now I want to extract the Array from it and need to use it as a separate pojo class so that I can iterate over each value..
Now the problem is, when I try to convert the complete String to Map and get the Array value from the map.. It transforms its format to MAp format like:
{FORM_RECEIVING_DATE = 12:00:00, etc..}
However json string should be {"FORM_RECEIVING_DATE": "12:00:00", etc..}
due to the MAp format its now allowing me to parse it using my POJO Class..
Please help to convert it to my JSONFormat ...
**NOTE: Please note that I can only use Jackson **.
CLASS A
ObjectMapper mapper2 = new ObjectMapper();
Map<String, Object> map;
map = mapper2.readValue(json, new TypeReference<Map<String, Object>>(){});
System.out.println("map: " + map.get("ROU_DATA") );
String array = map.get("ROU_DATA").toString();
String json2 = new ObjectMapper().writeValueAsString(array.replace("[", "").replace("]", ""));
String json3 = new ObjectMapper().writeValueAsString(json2);
System.out.println("json2>>" + json2);
System.out.println("json2>>" + json3);
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 1. convert JSON array to Array objects
ROU[] pp1 = mapper.readValue("{" + array.replace("=", ":") + "}", ROU[].class);
for (ROU person : pp1) {
System.out.println(person.getRemarks());
}
CLASS B
import com.fasterxml.jackson.annotation.JsonProperty;
public class ROU {
#JsonProperty("FORM_RECEIVING_TIME")
private String formdate;
#JsonProperty("REMARKS")
private String remarks;
public String getFormdate() {
return formdate;
}
public void setFormdate(String formdate) {
this.formdate = formdate;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
}

map.get("ROU_DATA") returns a List object, and the toString() method of List does not generate JSON text.
You don't need to convert back to a JSON text just to get the ROU[] created, just call convertValue(...).
String input = "{ \"password\":\"des123\",\"ROU_DATA\":[{\"FORM_RECEIVING_TIME\":\"12:00:00\",\"REMARKS\":\"Redemption of Unit\"}, {\"FORM_RECEIVING_TIME\":\"13:00:00\",\"REMARKS\":\"sALE of Unit\"}] }";
ObjectMapper mapper2 = new ObjectMapper();
Map<?, ?> json = mapper2.readValue(input, Map.class);
ROU[] pp1 = mapper2.convertValue(json.get("ROU_DATA"), ROU[].class);
for (ROU person : pp1)
System.out.println(person.getRemarks());
Output
Redemption of Unit
sALE of Unit

class A
public class ROU {
#JsonProperty("FORM_RECEIVING_TIME")
private String formdate;
#JsonProperty("REMARKS")
private String remarks;
public String getFormdate() {
return formdate;
}
public void setFormdate(String formdate) {
this.formdate = formdate;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
}
class B
public class ObjOuter {
private String password;
#JsonProperty("ROU_DATA")
private List<ROU> rous;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<ROU> getRous() {
return rous;
}
public void setRous(List<ROU> rous) {
this.rous = rous;
}
}
json to Object
ObjectMapper mapper = new ObjectMapper();
try {
ObjOuter outer = mapper.readValue(str, ObjOuter.class);
for (ROU rou : outer.getRous()) {
System.out.println(rou.getFormdate());
System.out.println(rou.getRemarks());
}
} catch (IOException e) {
e.printStackTrace();
}

Related

Java JSON Processing

I'm having a hard time processing the below JSON with Java, which is being returned from on an external Ansible playbook:
{"Sample":
{
"tag_description":"abc","tag_category_id":"def","tag_id":"ghi"
},
"Sample1":
{
"tag_description":"jkl","tag_category_id":"mno","tag_id":"pqr"
}
}
I've been able to successfully parse one section of the JSON using a custom deserializer, though it only ever gets the first section. Any ideas are hugely appreciated.
#JsonComponent
public class TagSerializer extends JsonDeserializer<Tag> {
#Override
public Tag deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException,
JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
JsonFactory factory = mapper.getFactory();
JsonNode treeNode = jsonParser.getCodec().readTree(jsonParser);
Iterator<Map.Entry<String, JsonNode>> fields = treeNode.fields();
String name = "";
// collect the tag name
Map.Entry<String, JsonNode> entry = fields.next();
name = entry.getKey();
// now that we have the tag name, parse it as a separate JSON object
JsonNode node = entry.getValue();
// get the values from the JSON
String description = node.get("tag_description").asText();
String category_id = node.get("tag_category_id").asText();
String tag_id = node.get("tag_id").asText();
return new Tag(name, category_id, description, tag_id);
}
}
I'm calling the method from a Spring Boot REST API endpoint, and my 'tag' model is a Spring entity:
'Tag' model:
#Entity
#JsonDeserialize(using = TagSerializer.class)
public class Tag {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
private String tag_category_id;
private String tag_description;
private String tag_id;
//JPA requires that a default constructor exists
//for entities
protected Tag() {}
public Tag(String name,
String tag_category_id,
String tag_description,
String tag_id) {
this.name = name;
this.tag_category_id = tag_category_id;
this.tag_description = tag_description;
this.tag_id = tag_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTag_category_id() {
return tag_category_id;
}
public void setTag_category_id(String tag_category_id) {
this.tag_category_id = tag_category_id;
}
public String getTag_description() {
return tag_description;
}
public void setTag_description(String tag_description) {
this.tag_description = tag_description;
}
public String getTag_id() {
return tag_id;
}
public void setTag_id(String tag_id) {
this.tag_id = tag_id;
}
public String toString() {
return "<Tag:[Name: " + this.name + "],[tag_category: "+
this.tag_category_id + "],[tag_description: "+
this.tag_description + "],[tag_id:"+this.tag_id+"]";
}
}
Spring Boot endpoint:
#PostMapping(value="/store", consumes = APPLICATION_JSON_VALUE)
public void tagJson(#RequestBody String json) {
// delete any existing tags
tagRepository.deleteAll();
//lets modify the json to make it look nicer
String modjson = "["+json+"]";
ObjectMapper mapper = new ObjectMapper();
try {
Tag[] tags = mapper.readValue(modjson, Tag[].class);
for (Tag t : tags)
tagRepository.save(t);
} catch (Exception exception) {
exception.printStackTrace();
}
}
If you are using Spring MVC consider explicitly declare desired type when referreing to #RequestBody and let the framework do the job for you
#PostMapping(value="/store", consumes = APPLICATION_JSON_VALUE)
public void tagJson(#RequestBody Map<String, Tag> json) {
// Do not mess with ObjectMapper here, Spring will do the thing for you
}
This isn't a direct answer but a guide in a possible direction, using Gson.
package test;
import java.util.Map;
import com.google.gson.Gson;
public class JsonTest {
public static void main(final String... args) {
new JsonTest().run();
}
public void run() {
final Gson gson = new Gson();
final Map<?, ?> result = gson.fromJson("{" +
" \"Sample\": {" +
" \"tag_description\": \"abc\"," +
" \"tag_category_id\": \"def\"," +
" \"tag_id\": \"ghi\"" +
" }," +
" \"Sample1\": {" +
" \"tag_description\": \"jkl\"," +
" \"tag_category_id\": \"mno\"," +
" \"tag_id\": \"pqr\"" +
" }" +
"}", Map.class);
System.out.println("Map size: " + result.size());
}
}
The resulting size is 2. The map entries are keyed Sample, Sample1, and the values are lists containing the nodes. You can see this using a debugger.

How to expand and object in JSON body?

I have the next classes to have the appropriate json bodies:
public class MyResponse {
private String meta;
private String info;
private String respOne;
//...
}
And
public class MyResponseNew {
private String meta;
private String info;
private String respNew;
private String respbBest;
//...
}
The JSONs I need:
{
"meta": "",
"info": "",
"respOne": ""
}
And
{
"meta": "",
"info": "",
"respNew": "",
"respbBest": ""
}
So, I want to extract general info to one class and have something like this:
public class GeneralSubResponse {
private String meta;
private String info;
//..
}
public class MyResponse {
/*#JsonExpanded*/
private GeneralSubResponse generalInfo;
private String respOne;
//...
}
String types - just for examples, there can be any object of any nesting...
Is it possible using Jackson lib? Or is there exist any other way to do something like that? The main concern is to not duplicate code for each Object.
You can do it with common class inheritance or adding it as unwrapped object:
Option 1: with Java inheritance:
public class MyResponse extends GeneralSubResponse {
private String respOne;
//...
}
public class MyResponseNew extends GeneralSubResponse{
private String respNew;
private String respbBest;
}
Option 2: JsonUnwrapped object as object property:
public class MyResponseUnwrapped{
#JsonUnwrapped
private GeneralSubResponse subResponse;
private String respOne;
}
public class MyResponseNewUnwrapped{
#JsonUnwrapped
private GeneralSubResponse subResponse;
private String respNew;
private String respbBest;
}
Test (both options):
public class Test {
public static String getJsonString(Object o){
ObjectMapper mapper = new ObjectMapper();
//For testing
try {
//Convert object to JSON string
String jsonInString = mapper.writeValueAsString(o);
//System.out.println(jsonInString);
return jsonInString;
} catch (JsonProcessingException e){
e.printStackTrace();
}
return null;
}
public static void main(String args[]){
MyResponse myResponse = new MyResponse();
myResponse.setInfo("info");
myResponse.setMeta("meta");
myResponse.setRespOne("respOne");
System.out.println(myResponse.getClass().getSimpleName() + " = " + Test.getJsonString(myResponse ));
System.out.println("------------------------------");
MyResponseNew myResponseNew = new MyResponseNew();
myResponseNew.setInfo("infoNew");
myResponseNew.setMeta("metaNew");
myResponseNew.setRespbBest("respBest");
myResponseNew.setRespNew("respNew");
System.out.println(myResponseNew.getClass().getSimpleName() + " = " + Test.getJsonString(myResponseNew));
System.out.println("------------------------------");
MyResponseUnwrapped myResponseUnwrapped = new MyResponseUnwrapped();
GeneralSubResponse subResponse = new GeneralSubResponse();
subResponse.setInfo("infoUnwrapped");
subResponse.setMeta("metaUnwrapped");
myResponseUnwrapped.setSubResponse(subResponse );
myResponseUnwrapped.setRespOne("respTwo");
System.out.println(myResponseUnwrapped.getClass().getSimpleName() + " = " + Test.getJsonString(myResponseUnwrapped));
System.out.println("------------------------------");
MyResponseNewUnwrapped myResponseNewUnwrapped = new MyResponseNewUnwrapped();
GeneralSubResponse subResponse2 = new GeneralSubResponse();
subResponse2.setInfo("infoNewUnwrapped");
subResponse2.setMeta("metaNewUnwrapped");
myResponseNewUnwrapped.setSubResponse(subResponse2 );
myResponseNewUnwrapped.setRespbBest("respBestUnwrapped");
myResponseNewUnwrapped.setRespNew("respNewUnwrapped");
System.out.println(myResponseNewUnwrapped.getClass().getSimpleName() + " = " + Test.getJsonString(myResponseNewUnwrapped));
}
}
Result:
MyResponse = {"meta":"meta","info":"info","respOne":"respOne"}
------------------------------
MyResponseNew = {"meta":"metaNew","info":"infoNew","respNew":"respNew","respbBest":"respBest"}
------------------------------
MyResponseUnwrapped = {"meta":"metaUnwrapped","info":"infoUnwrapped","respOne":"respTwo"}
------------------------------
MyResponseNewUnwrapped = {"meta":"metaNewUnwrapped","info":"infoNewUnwrapped","respNew":"respNewUnwrapped","respbBest":"respBestUnwrapped"}

JSON parsing through GSON returns null values

I am trying to read the values of a JSON output.
This is the JSON output:
{"nameOfSummoner":{"id":56529189,"name":"test","profileIconId":550,"summonerLevel":30,"revisionDate":1422110739000}}
And with the following code I am trying to read it:
final Connector connector = new Connector();
String response = connector.connect("link"); // (Returns a String value of the JSON)
final Gson gson = new Gson();
final Summoner summoner = gson.fromJson(response, Summoner.class); //Summoner is a model class
System.out.println(summoner);
Summoner class:
public class Summoner {
private String name;
private long profileIconId;
private long summonerLevel;
private long revisionDate;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public long getProfileIconId() {
return profileIconId;
}
public void setProfileIconId(final long profileIconId) {
this.profileIconId = profileIconId;
}
public long getSummonerLevel() {
return summonerLevel;
}
public void setSummonerLevel(final long summonerLevel) {
this.summonerLevel = summonerLevel;
}
public long getRevisionDate() {
return revisionDate;
}
public void setRevisionDate
(long revisionDate) {
this.revisionDate = revisionDate;
}
#Override
public String toString() {
return "Summoner{" +
"name='" + name + '\'' +
", profileIconId=" + profileIconId +
", summonerLevel=" + summonerLevel +
", revisionDate=" + revisionDate +
'}';
}
}
And I get the following output on the console:
Summoner{name='null', profileIconId=0, summonerLevel=0, revisionDate=0}
I have sadly no idea why this happens. Any help I get is appreciated. I am fairly sure it has to do with the JSON output that "nameOfSummoner" is on top and maybe that's why it does not read what is below.
As mentioned by #PeterMmm , your input is a map with 1 key-value pair.
You need to Create another POJO with Summoner object as attribute:
public class Sample {
private Summoner nameOfSummoner;
//getters and setters
}
and then try parsing. Or, you could create a Map and parse.
Map<String, Summoner> responseObj = new HashMap<String, Summoner>();
responseObj= gson.fromJson(response, responseObj.class);
Summoner obj = responseObj.get("nameOfSummoner");
You will also need to have "id" attribute in Summoner class I believe, else gson will throw an exception.

Mapping JSON into POJO using Gson

I have the following JSON to represent the server response for a salt request:
{
"USER":
{
"E_MAIL":"email",
"SALT":"salt"
},
"CODE":"010"
}
And i tried to map it with the following POJO:
public class SaltPOJO {
private String code = null;
private User user = null;
#Override
public String toString() {
return this.user.toString();
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public class User {
private String e_mail = null;
private String salt = null;
#Override
public String toString() {
return this.e_mail + ": " + this.salt;
}
public String getE_mail() {
return e_mail;
}
public void setE_mail(String e_mail) {
this.e_mail = e_mail;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
}
}
Now everytime i do this:
Gson gson = new Gson();
SaltPOJO saltPojo = gson.fromJson(json.toString(), SaltPOJO.class);
Log.v("Bla", saltPojo.toString());
The saltPojo.toString() is null. How can i map my JSON into POJO using Gson?
Is the order of my variables important for the Gson mapping?
Is the order of my variables important for the Gson mapping?
No, that's not the case.
How can i map my JSON into POJO using Gson?
It's Case Sensitive and the keys in JSON string should be same as variable names used in POJO class.
You can use #SerializedName annotation to use any variable name as your like.
Sample code:
class SaltPOJO {
#SerializedName("CODE")
private String code = null;
#SerializedName("USER")
private User user = null;
...
class User {
#SerializedName("E_MAIL")
private String e_mail = null;
#SerializedName("SALT")
private String salt = null;
You don't have proper mapping between your getter and setter. If you change your json to something like below, it would work:
{
"user":
{
"email":"email",
"salt":"salt"
},
"code":"010"
}
If you are getting json form third party then unfortunately, you would have to change your pojo or you could use adapter.

How to map dynamic json value to HashMap in Pojo

i use jackson for jax-rs handler
the json member is always same, only 1 of it member have dynamic value ..
this dynamic value could only be "" or json object
json possibility 1
{
"event":"test",
"eventInfo": ""
}
json possibility 2
{
"event" : "test",
"eventInfo" : {
"name" : "abc",
"last" : "def"
}
}
eventInfo value could only be "" or json
i try to map this json to MyBean.java
MyBean.java
public class MyBean{
private String event;
private Map<String, String> eventInfo = new HashMap<String, String>();
public String getEvent() {
return event;
}
public void setEvent(String event) {
this.event = event;
}
#JsonAnyGetter
public Map getEventInfo() {
return eventInfo;
}
#JsonAnySetter
public void setEventInfo(String name, String value) {
this.eventInfo.put(name, value);
}
}
the mapping process happen in MyService.java
MyService.java
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces("text/plain")
public String receiveClientStatus(MyBean status){
if(!status.getEventInfo().isEmpty()){
String last = status.getEventInfo().get("last").toString() ;
System.err.println( last );
}
return "ok";
}
jackson fail convert the json as show above to MyBean.java
How to do this?
forgive my english
thanks
The issue is with the setEventInfo() method of MyBean object. In one case the value assigned to it is empty which is treated as string in other case its a linked hashmap. So modify the argument to accept Object. like
class MyBean {
private String event;
private Map<String, String> eventInfo = new HashMap<String, String>();
public String getEvent() {
return event;
}
public void setEvent(String event) {
this.event = event;
}
#JsonAnyGetter
public Map getEventInfo() {
return eventInfo;
}
#JsonAnySetter
public void setEventInfo(Object eventObject) {
if(eventObject instanceof Map){
this.eventInfo.putAll((Map<String, String>) eventObject);
}
}
#Override
public String toString() {
return "MyBean [event=" + event + ", eventInfo=" + eventInfo + "]";
}
}
Now it should work. Eg
String json1 = "{ \"event\":\"test\", \"eventInfo\": \"\" }";
String json2 = "{\"event\":\"test\",\"eventInfo\":{\"name\":\"abc\",\"last\":\"def\"}}";
ObjectMapper mapper = new ObjectMapper();
try {
MyBean bean1 = mapper.readValue(json1, MyBean.class);
System.out.println(bean1);
MyBean bean2 = mapper.readValue(json2, MyBean.class);
System.out.println(bean2);
} catch (IOException e) {
e.printStackTrace();
}

Categories