I have written some code which saves the contents of a List<Class> to a JSON file, which looks kinda like this:
{ "firstName": "Name", "lastName": "LastName", "Email": "Email" } { "firstName": "Name2", "lastName": "LastName2", "Email": "Email2" }
Now I'm trying to input this file into my program, which works but only the first JSON Object is being returned. This is my code:
ObjectMapper mapper = new ObjectMapper();
JsonNode readFile = mapper.readTree(new File("path/to/file.json"));
How can I read the full JSON file and how can I add the contents of it to the same List mentioned above?
Every tutorial etc. I stumble upon only explains this using a single object.
Thank you!
You can do this:
Create a user class like this:
public class User {
private String email;
private String firstName;
private String lastName;
// Setters and getters
}
Now you can do this:
String json = yourJson;
ObjectMapper mapper = new ObjectMapper();
User[] userArray = mapper.readValue(json, User[].class);
List<User> userList = Arrays.asList(mapper.readValue(json, User[].class));
Related
I have a student.json and Student.java as follows:
public class Student {
private String name;
private String age;
}
[{"name": "John", "age": 18}, {"name": "Alex"}]
I read the json file and map to List<Student> as follows:
File inRulesFile = (new ClassPathResource("Student.json")).getFile();
ObjectMapper mapper = new ObjectMapper();
List<Student> students = Arrays.asList(mapper.readValue(inRulesFile, Student[].class));
So the output is [{John - 18},{Alex - null}]
I don't want DE-serialize null value. How can I do this?
This is actually a follow up for this question Recreate DTO class without field property instead of having it null using Gson/Jackson and Spring Boot. I originally posted it trying to make it work with Gson but only able to do it with Jackson using the #JsonInclude(JsonInclude.Include.NON_NULL) but haven't been able to find an equivalent for this with Gson so I can keep that as the library for the project.
Tried using #Expose(serialise=false, deserialise=false) where I had the #JsonInclude annotation or set that field to null as thought Gson by default would ignore that, but it doesn't seem to do it.
Finally, I tried to remove the #Expose annotation completely from to see if Gson would ignore that but not working either.
Pasting it here the main pieces for the issue as well as keeping the extra details added to the original post.
#Service
public class CategoryQueryServiceImpl implements CategoryQueryService {
#Autowired
private CategoryRepository categoryRepository;
#Autowired
private ReportRepository reportRepository;
ObjectMapper mapper = new ObjectMapper();
#Override
public CategoryQueryDto getCategory(UUID id) throws JsonProcessingException {
if (categoryRepository.findById(id).isPresent()) {
Category category = categoryRepository.findById(id).get();
CategoryQueryDto categoryQueryDto = new CategoryQueryDto(category.getId(), category.getTitle());
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String converter = gson.toJson(categoryQueryDto);
categoryQueryDto = gson.fromJson(converter, CategoryQueryDto.class);
// Jackson
//String converter = mapper.writeValueAsString(categoryQueryDto);
//categoryQueryDto = mapper.readValue(converter, CategoryQueryDto.class);
return categoryQueryDto;
} else {
return null;
}
}
#AllArgsConstructor
#NoArgsConstructor
#Data
public class CategoryQueryDto {
#Expose()
private UUID id;
#Expose()
private String title;
// Jackson
// #JsonInclude(JsonInclude.Include.NON_NULL)
private List<ReportQueryDto> reports = null;
public CategoryQueryDto(UUID id, String title) {
this.id = id;
this.title = title;
}
}
If anyone has any other ideas on how to do this please.
Thank you very much.
DO NOT serialize null fields (This is the default behavior of Gson serialization)
Employee employeeObj = new Employee(1, "John", "Smith", null);
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
System.out.println(gson.toJson(employeeObj));
Output:
{
"id": 1,
"firstName": "John",
"lastName": "Smith"
}
Serialize null fields (Custom Gson serialization with null values included in JSON output)
Employee employeeObj = new Employee(1, "John", "Smith", null);
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.serializeNulls()
.create();
System.out.println(gson.toJson(employeeObj));
Output:
{
"id": 1,
"firstName": "John",
"lastName": "Smith",
"emailId": null
}
It seems the default behaviour for Gson was not taking place as Spring Boot uses Jackson as the default serialisation library. Overwriting this by pasting the below line within the application.properties file has fixed the issue for me.
spring.mvc.converters.preferred-json-mapper=gson
I have a JSON structured like:
{
"id" : "123",
"name" : [ {
"id" : "234",
"stuff" : [ {
"id" : "345",
"name" : "Bob"
}, {
"id" : "456",
"name" : "Sally"
} ]
} ]
}
I want to map to the following data structure:
Class01
#Getter
public class Class01{
private String id;
#JsonDeserialize(using = Class01HashMapDeserialize.class)
private ArrayList<Class02> name;
}
Class02
#Getter
public class Class02{
private String id;
private ArrayList<Class03> stuff;
}
Class03
#Getter
public class Class03{
private String id;
private String name;
}
In my main Method im using an ObjectMapper with objectMapper.readValue(jsonString,new TypeReference<ArrayList<Class02>>(){}) to map this JSON to my Class01. This Class successfully deserealizes the Class02-array into the name array.
When it comes to the second array I don't know how to further deserialize as I am not able to access the json text from the class02 stuff entry.
#Override
public ArrayList<Class02> deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException {
ArrayList<Class02> ret = new ArrayList<Class02>();
ObjectCodec codec = parser.getCodec();
TreeNode classes02 = codec.readTree(parser);
if (classes02.isArray()) {
for (JsonNode class02 : (ArrayNode) classes02) {
if(classe02.get("stuff").isArray()){
ObjectMapper objectMapper = new ObjectMapper();
ArrayList<Class03> classes03 = objectMapper.readValue(class02.get("stuff").asText(), new TypeReference<ArrayList<Class03>>(){});
}
ret.add(new Class02(class02.get("id").asText(), classes03));
}
}
return ret;
}
Why did you put a #JsonDeserialize annotation ? Jackson shall be able to deserialize it just fine without any custom mapping:
#Getter
public class Class01{
private String id;
private ArrayList<Class02> name;
}
Also in a first pass, I would generate the getters/setters/constructor manually for the 3 classes. There may be issues with Lombok & Jackson that you may want to solve later once you made the first version of the code works (Can't make Jackson and Lombok work together)
And your reader shall be more like:
ObjectMapper objectMapper = new ObjectMapper();
String text = ... //Your JSon
Class01 class01 = objectMapper.readValue(text, Class01.class)
Lets say we have the following JSON example:
{
"teachers": [{
"id": "abc",
"payment": 10,
"name": "xyz",
"clases": ["1", "3"]
}, {
"id": "qwe",
"payment": 12,
"name": "xcv",
"classes": ["1", "2"]
}],
"classes": [{
"id": "1",
"room": 7
}, {
"id": "2",
"room": 1
}, {
"id": "3",
"room": 2
}]
}
I would like to deserialize it to Java objects (getters/setters ommited):
class Teacher {
private String id;
private double payment;
private String name;
private List<CLassRoom> classRooms;
}
class ClassRoom {
private String id;
private int room;
}
As you see, we have a references here. I know I can deserialize it with Jackson (and would like to) but the problem is that I cannot touch DTO itself (so annotations are not possible, would also like to avoid wrappers (many classes)). Also, it would be nice if the "configuration" of deserialization was in separate file (json schema for example). I would also like to avoid some tags given by user - he should only pass me the values. Moreover, he should know where is the error, if he made some mistake.
Also, it would be nice if I could manipulate name of field in json (some clients may have different habits).
I didn't find anything which satisffied all of above requirements(entity reference and error handling are the most important). However - I just have heard about json schema, so maybe it provides such functionality (but I didn't find it though). Any helpful reference/example/lib? I will appreciate any help.
Just to be correct - imagine that the given json is a RELATIONAL database snapshot of the instance. I just want to create whole entity like the hibernate (or actually JPA) does :)
1. add jar of import org.json.JSONObject.
2. JSONObject object = new JSONObject(list)
2.1 object.has("teachers") if it is exists
2.2 JSONArray teacherArray = (JSONArray) object.get("teachers");
2.3 JSONObject teacherJsonObject = teacherArray .getJSONObject(0);
(if you have more than jsonobject in json arrary then itrate it.)
2.4 if(teacherJsonObject .has("id"))//you can check existence like this.
String id=teacherJsonObject .getString("id");
String payment=teacherJsonObject .getString("payment");
String name=teacherJsonObject .getString("name");
It may not be the best solution, but it's a working one.
Let's create a Parser class like the following:
public class Parser {
private List<Teacher> teachers;
private List<ClassRoom> classes;
public void parse() {
for (Teacher teacher : teachers) {
for (String classRoomId : teacher.getClasses()) {
for (ClassRoom classRoom : classes) {
if (classRoom.getId().equals(classRoomId)) {
teacher.getClassRooms().add(classRoom);
}
}
}
}
}
}
Modify your ClassRoom class to have a getter on the id field:
public class ClassRoom {
private String id;
private int room;
public String getId() {
return id;
}
}
And your Teacher class to get the Ids of classes AND the classRooms references:
public class Teacher {
private String id;
private double payment;
private String name;
private String[] classes;
private List<ClassRoom> classRooms = new ArrayList<>();
public String[] getClasses() {
return classes;
}
public List<ClassRoom> getClassRooms() {
return classRooms;
}
}
If you use the Gson library, you could then just parse your JSON like that:
Gson gson = new Gson();
Parser parser = gson.fromJson(jsonString, Parser.class);
parser.parse;
Now, every teacher will have their classRooms correctly referenced.
I have a JSON String called primarySkillStr :
[
{
"id": 3,
"roleIds": [
2
],
"rating": 2
}
]
I try to map it to an object as follows:
primarySkillList = mapper.readValue(primarySkillStr,
new TypeReference<List<PrimarySkillDTO>>() {});
But when Iam converting this to a List then the roleIds List is null.
Am I doing something wrong, or is there any other way?
This is my DTO
public class PrimarySkillDTO {
private Integer id;
private Integer rating;
private List<Integer> roleIds;
private String name;
}
I have the following annotations in the PrimarySkillDTO class
#Data
#Builder
#AllArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
The problem is that your JsonNaming annotation requires snake_case and you are not using it.
To solve it
remove the annotation #JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
or, rename the variable in the JSON String to role_ids
SnakeCaseStrategy will map roleIds <--> role_ids, The following codes work for me:
ObjectMapper objectMapper = new ObjectMapper();
TypeReference<List<TestClass>> typeRef = new TypeReference<List<TestClass>>() {};
List<TestClass> testList = objectMapper.readValue(testStringObject, typeRef);