I have a String in my servlet which is of the following format.
{
"name": "Jam",
"noOfBooksRequired": "2",
"type": "Type 1",
"bookName": [
"The Magic",
"The Power"
]
}
where the bookName is an array. I want to access the values in the array and populate in the bean. But, when I try to convert the string to jsonobject, I am getting the following exception because bookName is an array com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY This is how I am trying to do it
JSONObject js= new JSONObject();
String inputData= request.getParameter("inputData");
HashMap<String, String> hmap= new HashMap<String, String>();
Type type = new TypeToken<HashMap<String, String>>(){}.getType();
hmap = gson.fromJson(inputData, type);
js.putAll(hmap);
What I am doing is, I convert the string to a map and then add it to the JSONObject.
Since there are many json serializers and not sure which is the best. Right now, I have net.sf.json.JSONObject and com.google.gson.JsonObject
Can someone help me to get this solved.
Thanks in advance
You can map your JSON to a POJO.
If the book will have more attributes besides the name, you'll need two POJOs, as you can see below.
A POJO for the book:
class Book {
private String name;
private String author;
public Book() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
And a POJO for the shelf, which have a list of books:
class Shelf {
private String name;
private Integer noOfBooksRequired;
private String type;
private List<Book> books;
public Shelf() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getNoOfBooksRequired() {
return noOfBooksRequired;
}
public void setNoOfBooksRequired(Integer noOfBooksRequired) {
this.noOfBooksRequired = noOfBooksRequired;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
}
Your JSON will look like this:
{
"name": "Jam",
"noOfBooksRequired": "2",
"type": "Type 1",
"books": [
{"name": "The Magic", "author": "John Doe"},
{"name": "The Power", "author": "Jane Doe"}
]
}
And then you can use Gson to parse your JSON:
Gson gson = new Gson();
Shelf shelf = gson.fromJson(inputData, Shelf.class);
Update
Considering your JSON looks like this (the book can be represented as a String):
{
"name": "Jam",
"noOfBooksRequired": "2",
"type": "Type 1",
"books": [
"The Magic",
"The Power"
]
}
Only one POJO with a list of String is enough:
class Shelf {
private String name;
private Integer noOfBooksRequired;
private String type;
private List<String> books;
public Shelf() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getNoOfBooksRequired() {
return noOfBooksRequired;
}
public void setNoOfBooksRequired(Integer noOfBooksRequired) {
this.noOfBooksRequired = noOfBooksRequired;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<String> getBooks() {
return books;
}
public void setBooks(List<String> books) {
this.books = books;
}
}
Related
Below is my JSON data. I want to convert this to POJOs to store the Name,id,profession in a header table and the respective Jsonarray field in a child table.
JSON:
{
"Name": "Bob",
"id": 453345,
"Profession": "Clerk",
"Orders": [
{
"Item": "Milk",
"Qty": 3
},
{
"Item": "Bread",
"Qty": 3
}
]
}
Entity classes:
public class User {
private String name;
private Integer id;
private String Profession;
private JsonArray Orders;
private UserCart userCart;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getProfession() {
return Profession;
}
public void setProfession(String profession) {
Profession = profession;
}
public JsonArray getOrders() {
return Orders;
}
public void setOrders(JsonArray orders) {
Orders = orders;
}
public UserCart getUserCart() {
return userCart;
}
public void setUserCart(UserCart userCart) {
this.userCart = userCart;
}
}
public class UserCart {
private String item;
private Integer qty;
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public Integer getQty() {
return qty;
}
public void setQty(Integer qty) {
this.qty = qty;
}
}
But when I do below; I get error
Cannot deserialize instance of org.json.JSONArray out of START_ARRAY
token
User user = new User();
JsonNode data = new ObjectMapper().readTree(jsonString);
user = headerMap.readValue(data.toString(), User.class);
How do I go about assigning the entire JSON to both the Java objects ?
Use List<UserCart> for array data in json and use #JsonProperty for mapping different json node name to java object field. No need to use extra field (JsonArray Orders) anymore.
#JsonProperty("Orders")
private List<UserCart> userCart;
I am fetching some json from a pojo class using GSON and hashmap. This is Pojo Class
public class NetworkConfiguration {
#SerializedName("GUID")
#Expose
private String gUID;
#SerializedName("Name")
#Expose
private String name;
#SerializedName("Type")
#Expose
private String type;
#SerializedName("WiFi")
#Expose
private WiFi wiFi;
public NetworkConfiguration() {
}
public NetworkConfiguration(String gUID, String name, String type, WiFi wiFi) {
super();
this.gUID = gUID;
this.name = name;
this.type = type;
this.wiFi = wiFi;
}
public String getGUID() {
return gUID;
}
public void setGUID(String gUID) {
this.gUID = gUID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public WiFi getWiFi() {
return wiFi;
}
public void setWiFi(WiFi wiFi) {
this.wiFi = wiFi;
}
}
This is how I am trying to get JSON
WiFi wiFi = new WiFi();
wiFi.setPassphrase(open_network_configuration_wifi_password_edit.getText().toString());
wiFi.setSecurity(spinner_open_network_configuration_wifi_security.getSelectedItem().toString());
wiFi.setSSID(open_network_configuration_wifi_ssid_edit.getText().toString());
if (open_network_configuration_wifi_autoconnect_option.isChecked()) {
wiFi.setAutoConnect(true);
} else {
wiFi.setAutoConnect(false);
}
Map<String, Object> openNetworkConfigurationMap = new HashMap<>();
networkConfigurations.add(new NetworkConfiguration(open_network_configuration_guid_edit.getText().toString(),
open_network_configuration_name_edit.getText().toString(), "WiFi", wiFi));
Gson gson = new Gson();
String json = gson.toJson(networkConfigurations);
Map<String,Object> result = new Gson().fromJson(json, Map.class);
openNetworkConfigurationMap.put("NetworkConfigurations", json);
And this is what I am getting
NetworkConfigurations= [{
"GUID": "a",
"Name": "Example A",
"Type": "WiFi",
"WiFi": {
"SSID": "Example A",
"Security": "None",
"AutoConnect": true
}
}]
And this is wrong. This is what I am expecting
"NetworkConfigurations": [{
"GUID": "a",
"Name": "Example A",
"Type": "WiFi",
"WiFi": {
"SSID": "Example A",
"Security": "None",
"AutoConnect": true
}
}]
The main thing which is kinda worry that I am getting an equal sign = but it should be : after the NetworkConfigurations
Any kind of help would be appreciated. Thanks in advance
Just add this in the end:
String json = gson.toJson(openNetworkConfigurationMap);
and print the output json
How do we create a json property:value dynamically by taking them as inputs from the user through a REST service, without having to have fields to hold the value.
Basically, the present output is :
{
"name": "X",
"price": "X",
"ticker": "X",
"status": "X",
"supplier": "X",
"attribute": [{
"key": "index",
"value": "Nasdaq"
},
{
"key": "priority",
"value": "high"
}
]
}
Required output is :
{
"name": "X",
"price": "X",
"ticker": "X",
"status": "X",
"supplier": "X",
"attribute": [{
"index": "Nasdaq"
},
{
"priority": "high"
}
]
}
Here, index and Nasdaq are the values given by the user, which is the key-value pair that is to be added to the attribute list.
The two POJO's used :
Stock.java
#XmlRootElement
public class Stock {
public Stock() {
}
public Stock(String name, double price, String ticker, String status, String supplier, List<KV> attribute) {
super();
this.name = name;
this.price = price;
this.ticker = ticker;
this.status = status;
this.supplier = supplier;
this.attribute = attribute;
}
private String name;
private double price;
private String ticker;
private String status;
private String supplier;
private List<KV> attribute;
public List<KV> getAttribute() {
return attribute;
}
public void setAttribute(List<KV> attribute) {
this.attribute = attribute;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getTicker() {
return ticker;
}
public void setTicker(String ticker) {
this.ticker = ticker;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getSupplier() {
return supplier;
}
public void setSupplier(String supplier) {
this.supplier = supplier;
}
}
And :
KV.java
public class KV {
private String key;
private String value;
public KV(String key, String value) {
super();
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Would prefer answers relating to usage of annotations or changes in the rest service, and not text processing at the end.
Okay, once you get the response you are getting currently then instead of a class "public class KV {} ", you can create a Hashmap,
& key of the Hashmap can hold the index/priority etc & value can hold Nasdaq/high.
Also name the Hashmap variable as "attribute".
So that you can extract the data from API using your current structure & then can convert it to one as I said above & send the response.
Try using Attributes class in java
Instead of defining a list of object you can just define
Attribute attributes;
For more details about how Attribute class works visit https://docs.oracle.com/javase/8/docs/api/org/xml/sax/Attributes.html
I have a JSON file like this:
[
{
"id": "1",
"name": "test1",
"childrens": [
{
"id": "14",
"name": "test2",
"childrens": [
]
}
]
}
]
The model class:
public class Model {
private int id;
private String name;
}
And my parse method:
public List< Model > parseJSONService(JSONArray jsonArray) {
Gson gson = new Gson();
Model[] model = gson.fromJson(jsonArray.toString(),
Model[].class);
return Arrays.asList(model);
}
why not parse the json string directly? this is what i did, achieved the same thing you looking for i guess:
public class GsonPlay {
public static void main(String args[]) {
String testString = "[{\"id\": \"1\",\"name\": \"test1\",\"childrens\": [{\"id\": \"14\",\"name\": \"test2\",\"childrens\": []}]}]";
List<Model> modelList = parseJsonService(testString);
System.out.println(modelList);
}
private static List<Model> parseJsonService(String testString) {
Gson gson = new Gson();
Model[] models = gson.fromJson(testString, Model[].class);
return Arrays.asList(models);
}
}
class Model {
private int id;
private String name;
private List<Model> childrens;
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 List<Model> getChildrens() {
return childrens;
}
public void setChildrens(List<Model> childrens) {
this.childrens = childrens;
}
}
You can also have a look at this for further ideas:
Given I have the following json:
{
"Company": {
"name": "cookieltd",
"type": "food",
"franchise_location": [
{
"location_type": "town",
"address_1": "5street"
},
{
"location_type": "village",
"address_1": "2road"
}
]
}
}
How can it be binded to the following object classes using Jackson?:
1) Company class
public class Company
{
String name, type;
List<Location> franchise_location = new ArrayList<Location>();
[getters and setters]
}
2) Location class
public class Location
{
String location_type, address_1;
[getters and setters]
}
I have done:
String content = [json above];
ObjectReader reader = mapper.reader(Company.class).withRootName("Company"); //read after the root name
Company company = reader.readValue(content);
but I am getting:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "franchise_location"
As far as I can tell, you are simply missing an appropriately named getter for the field franchise_location. It should be
public List<Location> getFranchise_location() {
return franchise_location;
}
(and the setter)
public void setFranchise_location(List<Location> franchise_location) {
this.franchise_location = franchise_location;
}
Alternatively, you can annotate your current getter or field with
#JsonProperty("franchise_location")
private List<Location> franchiseLocation = ...;
which helps to map JSON element names that don't really work with Java field name conventions.
The following works for me
public static void main(String[] args) throws Exception {
String json = "{ \"Company\": { \"name\": \"cookieltd\", \"type\": \"food\", \"franchise_location\": [ { \"location_type\": \"town\", \"address_1\": \"5street\" }, { \"location_type\": \"village\", \"address_1\": \"2road\" } ] } }";
ObjectMapper mapper = new ObjectMapper();
ObjectReader reader = mapper.reader(Company.class).withRootName(
"Company"); // read after the root name
Company company = reader.readValue(json);
System.out.println(company.getFranchise_location().get(0).getAddress_1());
}
public static class Company {
private String name;
private String type;
private List<Location> franchise_location = new ArrayList<Location>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<Location> getFranchise_location() {
return franchise_location;
}
public void setFranchise_location(List<Location> franchise_location) {
this.franchise_location = franchise_location;
}
}
public static class Location {
private String location_type;
private String address_1;
public String getLocation_type() {
return location_type;
}
public void setLocation_type(String location_type) {
this.location_type = location_type;
}
public String getAddress_1() {
return address_1;
}
public void setAddress_1(String address_1) {
this.address_1 = address_1;
}
}
and prints
5street
my solution for JSON is always GSON, you can do some research on that, as long as you have the correct structure of class according to the JSON, it can automatically transfer from JSON to object:
Company company = gson.fromJson(json, Company.class);
GSON is so smart to do the convertion thing!
enjoy GSON !