I have a json file like this:
{
"Student" : [
{
"name": "john",
"age": 12
}, {
"name": "jack",
"age": 20
}
]
}
and my Student class is:
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
I want to make a Student Instance with name "jack" by using json
how can I do it?
Make Another Class Students which contain List<Student>.
public class Students {
List<Student> Student;
public List<Student> getStudents() {
return Student;
}
public void setStudent(List<Student> students) {
this.Student=students;
}
}
Gson gson = new Gson();
String jsonString = "Your Json String";
Students student = gson.fromJson(jsonString, Students.class);
I use org.json.simple library when I parse JSON
Excample:
excample App.java,
excample Information.java
List<Information> parseInformationObject(JSONArray infoList) {
List<Information> in = new ArrayList<>();
infoList.forEach(emp -> {
JSONObject info = (JSONObject) emp;
String id = info.get("id").toString();
String state = info.get("state").toString();
String type = null;
if (info.get("type") != null) {
type = info.get("type").toString();
}
String host = null;
if (info.get("host") != null) {
host = info.get("host").toString();
}
long timestamp = (long) info.get("timestamp");
in.add(new Information(id, state, type, host, timestamp));
});
return in;
}
Related
How to validate each of the names, ages and descriptions irrespective of json array index? It will kind of search that we need to validate on the basis of name, age and description with age is matching or not.
[
{
"Name": "Shobit",
"transactionDate": 1623049638000,
"age": "18",
"description": "My item for new collection addition into system with age 18"
},
{
"Name": "Neha",
"transactionDate": 1623049877000,
"age": "20",
"description": "My item for new collection addition into system with age 20"
}
]
You can convert your data to JSONArray and check each item as a JSONObject for example
JSONArray array = new JSONArray(data);
for(int i = 0; i < array.length() ; i++) {
JSONObject user = array.getJSONObject(i);
String name = user.getString("Name");
long transactionDate = user.getLong("transactionDate");
int age = user.getInt("age");
String description = user.getString("description");
// Validate here
}
Or move the validation to another method for example
JSONArray array = new JSONArray(data);
for(int i = 0; i < array.length() ; i++) {
JSONObject user = array.getJSONObject(i);
boolean isValidInfo = isValidateUser(user);
}
Validation method
public boolean isValidateUser(JSONObject user) {
String name = user.getString("Name");
long transactionDate = user.getLong("transactionDate");
int age = user.getInt("age");
String description = user.getString("description");
// Validate here
}
For java you can use the library "org.json"
Add in your pom.xml dependency:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
Now you can use the next solution with java 8 :
JSONArray jsonArray = new JSONArray(yourJsonArray);
IntStream.range(0, jsonArray.length()).forEachOrdered(index -> {
// below the solution #AmrDeveloper
JSONObject user = jsonArray.getJSONObject(index);
String name = user.getString("Name");
long transactionDate = user.getLong("transactionDate");
int age = user.getInt("age");
String description = user.getString("description");
// Validate here
});
OR USE other libraries.
Example with Jackson
Add dependency:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.2</version>
</dependency>
Create POJO:
public class User {
private String name;
private Long transactionDate;
private Integer age;
private String description;
public User(String name, Long transactionDate, Integer age, String description) {
this.name = name;
this.transactionDate = transactionDate;
this.age = age;
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getTransactionDate() {
return transactionDate;
}
public void setTransactionDate(Long transactionDate) {
this.transactionDate = transactionDate;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Create method:
public <T> Optional<List<T>> buildListObjectsFromJson(String jsonObjectsList, Class<T> clazz) {
LOGGER.info("Try to build list objects from json....");
try {
ObjectMapper objectMapper = new ObjectMapper();
List<T> objectsList = objectMapper
.readValue(jsonObjectsList, objectMapper.getTypeFactory()
.constructCollectionType(ArrayList.class, clazz));
LOGGER.info("Objects list created successfully! List size = {}", objectsList.size());
return Optional.of(objectsList);
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("Can't build List objects by json: {}", jsonObjectsList);
}
return Optional.empty();
}
And create use next example:
List<User> users = buildListObjectsFromJson(yourJsonArray, User.class).orElse(new ArrayList<>());
This way you can work with this data as a collection.
I have a file called persons.json:
[
{
"id": 1,
"name": "The Best",
"email": "thenextbigthing#gmail.com",
"birthDate": "1981-11-23"
},
{
"id": 2,
"name": "Andy Jr.",
"email": "usa#gmail.com",
"birthDate": "1982-12-01"
},
{
"id": 3,
"name": "JohnDoe",
"email": "gameover#gmail.com",
"birthDate": "1990-01-02"
},
{
"id": 4,
"name": "SomeOne",
"email": "rucksack#gmail.com",
"birthDate": "1988-01-22"
},
{
"id": 5,
"name": "Mr. Mxyzptlk",
"email": "bigman#hotmail.com",
"birthDate": "1977-08-12"
}
]
I'd like to parse this file into an ArrayList with FasterXML, possibly with it's ObjectMapper() function and then being able to access each value (id, name, etc.) individually as a String when iterating through the newly created ArrayList. How could I do that? I don't even know what kind of list I could/should use in order to get access to each value individually. I'm kind of stuck here. List<???>
First of all:
FasterXML uses Jackson underneath to parse/produce json.
Now: to use Jackson, first of all create a container object for the data of your json, which we will call Person
public class Person {
private int id;
private String name, email;
#JsonFormat
(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date birthDate;
//add here getters and setters ...
}
At this point, supposing you have pathToPersonsJsonFile as a string containing the path to your persons.json, you can use your file like this:
byte[] jsonData = Files.readAllBytes(Paths.get(pathToPersonsJsonFile));
ObjectMapper objectMapper = new ObjectMapper();
Person[] parsedAsArray = objectMapper.readValue(jsonData, Person[].class); //array
ArrayList<Persons> persons = new ArrayList<>(Arrays.asList(parsedAsArray)); //your list
Note: JsonFormat enables to declare which format that value has on your json.
First you should create POJO for storing info:
public class Person {
Long id;
String name;
String email;
#JsonFormat("yyyy-mm-dd")
Date birthDate;
...
}
next you should call:
List<Person> myObjects = new ObjectMapper().readValue(jsonInput, new TypeReference<List<Person>>(){});
This should be enough
ObjectMapper objectMapper = new ObjectMapper();
List<Person> list = objectMapper.readValue(new File("path_to_persons.json"), new TypeReference<List<Person>>(){});
public class Person {
private String id;
private String name;
private String email;
private String birthDate;
.....
}
1) First create class Person.java
2) Then read the persons.json file and create a JSONArray from it.
3) Then parse as given below:
class Person{
private int id;
private String name;
private String email;
private String birthDate;
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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate) {
this.birthDate = birthDate;
}
}
public List<Person> getPersonList(JSONArray dataArray){
List<Person> personList = new ArrayList<>();
for(int i=0; i<dataArray.length(); i++){
try {
JSONObject personJsonObject = dataArray.getJSONObject(i);
Person person = new Person();
if(personJsonObject.has("id") && !personJsonObject.isNull("id")){
person.setId(personJsonObject.getInt("id"));
}
if(personJsonObject.has("name") && !personJsonObject.isNull("name")){
person.setName(personJsonObject.getString("name"));
}
if(personJsonObject.has("email") && !personJsonObject.isNull("email")){
person.setEmail(personJsonObject.getString("email"));
}
if(personJsonObject.has("birthDate") && !personJsonObject.isNull("birthDate")){
person.setBirthDate(personJsonObject.getString("birthDate"));
}
personList.add(person);
}catch (JSONException e){
}
}
return personList;
}
4) Then use this list wherever you want.
I have gone through the threads from SOF which talks about getting nested JSON using GSON. Link 1 Link 2. My JSON file is as shown below
{
"Employee_1": {
"ZipCode": 560072,
"Age": 50,
"Place": "Hawaii",
"isDeveloper": true,
"Name": "Mary"
},
"Employee_2": {
"ZipCode": 560072,
"Age": 80,
"Place": "Texas",
"isDeveloper": true,
"Name": "Jon"
}
}
my classes are as shown below
public class Staff {
String Employee_1 ;
}
class addnlInfo{
String Name;
String Place;
int Age;
int Zipcode;
boolean isDeveloper;
}
The deserializer class which I built is as shown below
class MyDeserializer implements JsonDeserializer<addnlInfo>{
public addnlInfo deserialize1(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException
{
// Get the "content" element from the parsed JSON
JsonElement content = je.getAsJsonObject().get("Employee_1");
// Deserialize it. You use a new instance of Gson to avoid infinite recursion
// to this deserializer
return new Gson().fromJson(content, addnlInfo.class);
}
#Override
public TokenMetaInfo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
// TODO Auto-generated method stub
return null;
}
The main file
Gson gson = new GsonBuilder()
.registerTypeAdapter(addnlInfo.class, new MyDeserializer())
.create();
String jsonObject= gson.toJson(parserJSON);
addnlInfo info= gson.fromJson(jsonObject, addnlInfo .class);
System.out.println(info.Age + "\n" + info.isDeveloper + "\n" + info.Name + "\n" + info.Place);
Staff parentNode = gson.fromJson(jsonObject, Staff.class);
System.out.println(parentNode.Employee_1);
The problem:
My Subparent element (e.g. 'Employee_1') keeps changing. Do I have to construct multiple deserializers?
Also, I get "Expected a string but was BEGIN_OBJECT" which I understand as we use nestedJSON.
I am not sure how your classes translate to your JSON, but you are making this too complex.
I renamed fields and class names to adhere to Java standards.
Main.java
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
public class Main {
public static void main(String[] args) {
Map<String, Staff> employees = new LinkedHashMap<String, Staff>();
employees.put("Employee_1", new Staff(new Info("Mary", "Hawaii", 50, 56072, true)));
employees.put("Employee_2", new Staff(new Info("Jon", "Texas", 80, 56072, true)));
String jsonString = new GsonBuilder().setPrettyPrinting().create().toJson(employees);
System.out.println("# SERIALIZED DATA:");
System.out.println(jsonString);
Type mapOfStaff = new TypeToken<Map<String, Staff>>() {}.getType();
Map<String, Staff> jsonObject = new Gson().fromJson(jsonString, mapOfStaff);
System.out.println("\n# DESERIALIZED DATA:");
for (Entry<String, Staff> entry : jsonObject.entrySet()) {
System.out.printf("%s => %s%n", entry.getKey(), entry.getValue());
}
}
}
Staff.java
public class Staff {
private Info info;
public Staff(Info info) {
this.info = info;
}
public Info getInfo() {
return info;
}
public void setInfo(Info info) {
this.info = info;
}
#Override
public String toString() {
return String.format("Staff [info=%s]", info);
}
}
Info.java
public class Info {
private String name;
private String place;
private int age;
private int zipcode;
private boolean developer;
public Info(String name, String place, int age, int zipcode, boolean developer) {
this.name = name;
this.place = place;
this.age = age;
this.zipcode = zipcode;
this.developer = developer;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getZipcode() {
return zipcode;
}
public void setZipcode(int zipcode) {
this.zipcode = zipcode;
}
public boolean isDeveloper() {
return developer;
}
public void setDeveloper(boolean developer) {
this.developer = developer;
}
#Override
public String toString() {
return String.format(
"Info [name=%s, place=%s, age=%d, zipcode=%d, developer=%b]",
name, place, age, zipcode, developer
);
}
}
Output
# SERIALIZED DATA:
{
"Employee_1": {
"info": {
"name": "Mary",
"place": "Hawaii",
"age": 50,
"zipcode": 56072,
"developer": true
}
},
"Employee_2": {
"info": {
"name": "Jon",
"place": "Texas",
"age": 80,
"zipcode": 56072,
"developer": true
}
}
}
# DESERIALIZED DATA:
Employee_1 => Staff [info=Info [name=Mary, place=Hawaii, age=50, zipcode=56072, developer=true]]
Employee_2 => Staff [info=Info [name=Jon, place=Texas, age=80, zipcode=56072, developer=true]]
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;
}
}
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 !