I intend to create a JSON Array with the following structure. The metadata tag is going to constant in all the entries. I am stumped.
[{
"metadata": {
"Value": "String"
},
"name": "String",
"id": "String"
},
{
"metadata": {
"Value": "String"
},
"name": "String",
"id": "String"
}
]
public class yourJsonObject {
private Map<String, String> metadata;
private String name;
private string id;
public yourJsonObject() {
}
public Map<String, String> getMetadata(){
return metadata;
}
public void setMetadata(Map<String, String> metadata){
this.metadata = metadata;
}
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId(){
return id;
}
public void setId(String id){
this.id = id;
}
}
Then somewhere else you can just do this:
ObjectMapper mapper = new ObjectMapper(); // create once, reuse
yourJsonObject example = new yourJsonObject(); // have your POJO you want to save
mapper.writeValue(new File("result.json"), example);
To read you can just use:
ObjectMapper mapper = new ObjectMapper(); // create once, reuse
yourJsonObject value = mapper.readValue(new File("data.json"), yourJsonObject .class);
Both snippets are taken from my linked wiki article from jackson themselves.
Jackson should automatically be able to parse this POJO to an equivalent JSON if configured correctly.
Note: Jackson has to be globally registered and has to know about it. Please read the wiki of what you use to know about it... Jackson in 5 Minutes
Else you could just manually build the JSON like Neeraj said.
JSONArray array = new JSONArray(); // Create JSONArray Object
JSONObject jsonObject = new JSONObject(); // Your JSONObject which gets added into array
jsonObject.put("metadata",new MetaDataCustomClass("SomeRandomStringValue"));
jsonObject.put("name", "Neeraj");
jsonObject.put("id", "123");
array.add(jsonObject); // Here you push the jsonObject into Array.
Note: MetaDataCustomClass is just a custom Class having a Value instance variable of type String.
Class MetaDataCustomClass {
private String value;
public MetaDataCustomClass(String value){
this.value = value;
}
}
Related
I am trying to map my incoming json payload to an arraylist of my model class.
I have a solution but its unintuitive.
I try to do this but get compilation errors-
ObjectMapper mapper = new ObjectMapper();
ArrayList<ModelClass> = mapper.readValue(items, RoleAttribute.class);
FYI I am trying to save this data in a Mongo collection.
Controller-
#PostMapping(value="/resource", consumes="application/json")
public Iterable<ModeClass> createResources(#RequestBody JSONObject requestBody ) throws JsonParseException, JsonMappingException, IOException {
System.out.println(requestBody.getClass());
return serviceImpl.saveResources(requestBody);
}
Model class-
#Data
#AllArgsConstructor
#Document(collection="collection-name")
public
class ModelClass{
#Field
private String ID;
#Field
private String description;
}
The payload is coming in the following format-
{
"data": [
{
"ID": "1",
"description": "desc1"
},
{
"ID": "2",
"description": "desc2"
},
{
"ID": "3",
"description": "desc3"
},
{
"ID": "4",
"description": "desc4"
}
....
]
}
I know I should be using jackson but I can't seem to figure this out. Do I need to change my POJO? Do I need to create custom Jackson config?
You can do it with json annotation. I also notice that your values are represented as data in json so that also needs to be taken care of. Look at below code. That will solve your problem.
import com.fasterxml.jackson.annotation.JsonProperty;
#Data
#AllArgsConstructor
#Document(collection="collection-name")
public class ModelClass{
#Field
#JsonProperty("ID")
private String classID;
#Field
#JsonProperty("description")
private String classDescription;
public String getClassID() {
return classID;
}
public void setClassID(String classID) {
this.classID = classID;
}
public String getClassDescription() {
return classDescription;
}
public void setClassDescription(String classDescription) {
this.classDescription = classDescription;
}
}
And wrapper Data class as below
class Data {
ModelClass[] data;
public ModelClass[] getData() {
return data;
}
public void setData(ModelClass[] data) {
this.data = data;
}
}
And json conversion code as below
ObjectMapper mapper = new ObjectMapper();
// json is your incoming json as a string. You can put inputstream also
Data values = mapper.readValue(json, Data.class);
System.out.println(values.getData().length);
System.out.println(values.getData()[0].getClassID());
You would need a container class for the data field, something like:
#Data
#Document(collection="collection-name")
public class DataClass{
private List<ModelClass> data;
}
Doing it via Jackson should be automatic this way, in controller:
public Iterable<ModeClass> createResources(#RequestBody DataClass requestBody ) {
i don't arrive to get the name of the containerStatuses.
I tried this (regarding a precedent post), the error is reported on the get("name") with "The method get(String) is undefined for the type JsonElement".
Thanks for help
JsonObject data = new Gson().fromJson(myjsoncontent, JsonObject.class);
JsonArray items = data .get("items").getAsJsonArray();
for(JsonElement element : items){
JsonObject object = element.getAsJsonObject();
String containerstatusesname = object.get("status").getAsJsonObject().get("containerStatuses").getAsJsonArray().get(0).get("name").getAsString();
}
// My Json Content
{
"kind": "Space",
"apiVersion": "v1",
"metadata": {
"selfLink": "something",
"resourceVersion": "something"
},
"items": [
{
"status": {
"containerStatuses": [
{
"name": "thisismyname"
}
]
}
}
]
}
Why are you using gson emulating JSON.parse? Is using a sledgehammer to crack a nut.
If you want to use gson it's better to create a class that matches your json data as:
public class ApiResponse {
private String kind;
private String apiVersion;
private Metadata metadata;
private List<Item> items;
public List<String> getAllNames() {
List<String> allNames = new ArrayList();
for (Item item: items) {
allNames.add(item.getStatus().get(0).getName());
}
return allNames;
}
public String getFirstName() {
if (items.length == 0 || items.get(0).getStatus().length == 0) {
return "";
}
return items.get(0).getStatus().get(0).getName();
}
class Metadata {
private String selfLink;
private String resourceVersion;
}
class Item {
private List<StatusContainer> status;
List<StatusContainer> getStatus() {
return status;
}
}
class StatusContainer {
private String name;
String getName() {
return name;
}
}
}
And then execute:
ApiResponse response = gson.fromJson(myjsoncontent, ApiResponse.class);
String firstName = response.getFirstName();
And this way the response object will contain all the data of the parsed json. Notice you'll need to add the getters to access this properties if are kept private.
No need to emulate the result of JSON.parse and have JsonObject, JsonArray...
You have to change
.get(0).get("name")
to
.get(0).getAsJsonObject().get("name")
JsonArray returns JsonElements when you iterate over it
Get the Array Element as Object cause its structured as Object
.getAsJsonArray().get(0).getAsJsonObject().get("name").getAsString();
I have a response that returns a json object in following format:
{
"playerId": "001",
"name": "michel",
"age": 21,
"nation": "USA",
"ratings": [
{
"type": "speed",
"score": "0121"
},
{
"type": "accuracy",
"score": "85"
}
],
"teaminfo": {
"teamName": "HON",
"isValid": "true"
}
}
and I have a Java Class as :
public class MyRider {
public String playerId;
public String name;
public int age;
public String speed;
public String accuracy;
public String teamName;
public String isValid;
//getter, setter...
}
I want to map the JSON object into Java object using GSON.
I tried using JsonDeserializationContext deserialize, and it returned null for the nested values in JSON.
Without custom deserializer
If you cannot change the JSON to return exactly what you want, I suggest you create classes to match it:
MyRider:
public class MyRider {
private String playerId;
private String name;
private int age;
private String nation;
private List<Rating> ratings;
private TeamInfo teaminfo;
// getters, setters, toString override
}
Rating:
public class Rating {
private String type;
private String score;
// getters, setters, toString override
}
TeamInfo:
private static class TeamInfo {
private String teamName;
private String isValid;
// getters, setters, toString override
}
Then simply deserialize as normal:
MyRider rider = gson.fromJson(json, MyRider.class);
If you need exactly the fields you've specified in MyRider in your question, consider a transformer class to map the full class above to your needs.
With custom deserializer
It's also possible to do this with a custom deserializer, but slightly pointless as GSON provides the normal mapping for you which you can then adapt.
Here is an example with a deserializer:
public class MyRiderDeserializer implements JsonDeserializer<MyRider> {
#Override
public MyRider deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException {
MyRider rider = new MyRider();
if(json.isJsonObject()) {
JsonObject riderObj = json.getAsJsonObject();
rider.setPlayerId(riderObj.get("playerId").getAsString());
rider.setName(riderObj.get("name").getAsString());
rider.setAge(riderObj.get("age").getAsInt());
JsonArray ratingsArray = riderObj.get("ratings").getAsJsonArray();
for(JsonElement ratingElem : ratingsArray) {
JsonObject ratingObj = ratingElem.getAsJsonObject();
String type = ratingObj.get("type").getAsString();
switch(type) {
case "speed":
rider.setSpeed(ratingObj.get("score").getAsString());
break;
case "accuracy":
rider.setAccuracy(ratingObj.get("score").getAsString());
break;
default:
break;
}
}
JsonObject teamInfo = riderObj.get("teaminfo").getAsJsonObject();
rider.setTeamName(teamInfo.get("teamName").getAsString());
rider.setIsValid(teamInfo.get("isValid").getAsString());
}
return rider;
}
}
Note this does not include any checks to validate whether the properties are actually there and is the simplest possible custom deserializer I could think of. To use it, you must register the type adapter at Gson creation time:
Gson gson = new GsonBuilder()
.registerTypeAdapter(MyRider.class, new MyRiderDeserializer())
.create();
MyRider myRider = gson.fromJson(reader, MyRider.class);
I've got an JSON string from my API, looks like this:
[
{
"id": "abc",
"data": {
"Name": "Peter",
"Date": "2017/12/01"
}
},
{
"id": "def",
"data": {
"Name": "Tina",
"Date": "2017/12/20"
}
},
{
"id": "ghi",
"data": {
"Name": "Amy",
"Date": "2017/12/16"
}
}
]
Then, I use (java):
Gson gson = new Gson();
Type resultType = new TypeToken<List<Map<String, Object>>>() {
}.getType();
List<Map<String, Object>> result = gson.fromJson(info, resultType);
if I call result.get(0).toString());
then it returned:
{id=abc, data={Name=Peter, Date=2017/12/01}}
if I call result.get(0).get("id").toString();
then it returned
abc
Now I want to get the data of "data", when I call result.get(0).get("data").toString();
then it returned
{Name=Peter, Date=2017/12/01}
Finally I want to get the "Name" info, but when I tried to convert this string to Map, it cause some problem, the code is like this:
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> myMap = gson.fromJson(str, type);
This doesn't work. I found that maybe the string is not a general type of JSON, it is like "Name=Peter, Date=2017/12/01", but it needs "Name": "Peter", "Date": "2017/12/01" , right? Is that the problem? How can I get the data of Name? Can anyone help me?
Updated:
I found that if "Name" = "", then I couldn't get it as string type, I cannot use "data.get("Name");". But I still need it. Anyone can fix it? Thanks.
You can directly convert the response into the POJO/Model class. Check this and this
You don't need manual parsing, if you are using Gson. See how-
List<Response> responseList = new Gson().fromJson(yourJson, new TypeToken<List<Response>>() {
}.getType());
Data data = responseList.get(0).getData();
String id = responseList.get(0).getId();
String date = data.getDate();
String name = data.getName();
Isn't this magic? No manual parsing at all.
Response.java class
public class Response {
private Data data;
private String id;
public void setData(Data data) {
this.data = data;
}
public Data getData() {
return data;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
Data.java class
public class Data {
private String date;
private String name;
public void setDate(String date) {
this.date = date;
}
public String getDate() {
return date;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
How to generate Pojo classes? So here is several websites jsonschema2pojo. Also many Android Studio plugins available, I use RoboPOJOGenerator.
First of all, your JSON is malformed, it shouldn't have a comma after date.
and to answer your question, don't use map at all.
If you really want to do it without creating a model and additional classes, do it this way:
Gson gson = new Gson();
Type resultType = new TypeToken<List<JsonObject>>() {}.getType();
List<JsonObject> result = gson.fromJson(info, resultType);
System.out.println(result.get(0).get("data").toString());
JsonObject data = result.get(0).get("data").getAsJsonObject();
System.out.println(data.get("Name"));
I am calling a webservice which gives me a json like this
{
"discussions": [{
"id": 54,
"name": "Test Discusssion",
"discussion": 41,
"created": 1472816138,
"modified": 1472816138,
"subject": "Test Discusssion",
"message": "<p>Welcome all to test discussion<\/p>",
}],
"warnings": []
}
But in android I am parsing it as
ArrayList<MoodleDiscussion> mDiscussions = gson.fromJson(reader,
new TypeToken<List<MoodleDiscussion>>() {
}.getType());
And the error I am getting is
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT
I want to convert the received json into an array how should I ?
Here is the MoodleDiscussion class
public class MoodleDiscussion extends SugarRecord < MoodleDiscussion > {#
SerializedName("id") int discussionid;#
SerializedName("name") String name;#
SerializedName("subject") String subject;
public int getDiscussionid() {
return discussionid;
}
public String getName() {
return name;
}
public int getUserid() {
return userid;
}
public String getSubject() {
return subject;
}
}
The list you're trying to parse is contained within a nested json data structure that also needs to be represented in java classes if Gson is to parse it correctly.
You'll need a container class that looks something like this:
public class MoodleDiscussionResponse {
private List<MoodleDiscussion> discussions;
private List<Object> warnings;
public List<MoodleDiscussion> getDiscussions() {
return discussions;
}
public List<Object> getWarnings() {
return warnings;
}
}
Then you should be able to read it like so:
MoodleDiscussionResponse response = gson.fromJson(reader, MoodleDiscussionResponse.class);
List<MoodleDiscussion> mDiscussions = response.getDiscussions();
Define class the same:
class Discussion implements Serializable
{
#SerializedName("id")
int id;
#SerializedName("name")
String name;
#SerializedName("discussion")
String discussion;
bla bla
}
and:
class ResultResponse implements Serializable
{
#SerializedName("discussions")
List<Discussion> mDiscussion = new ArrayList<>();
}
I think that is enough to parser using gson.
You can not using below code in this case :)
ArrayList<MoodleDiscussion> mDiscussions = gson.fromJson(reader,
new TypeToken<List<MoodleDiscussion>>() {
}.getType());
you can parse in two ways first get array list of json object and loop it
JSONArray discussionsList = obj1.getJSONArray("discussions");
for (int i = 0; i < discussionsList.length(); i++) {
JSONObject jsonObject = orderList.getJSONObject(i);
Type type = new TypeToken<MoodleDiscussion>() {
}.getType();
CompletedOrderData completedOrderData = new Gson().fromJson(jsonObject.toString(), type);
disscussionDataArrayList.add(completedOrderData);
and second way is parse jsonArray object as below
Type type = new TypeToken<ArrayList<MoodleDiscussion>>() {
}.getType();
disscussionDataArrayList=new Gson().fromJson(orderList,type);