Flattening a nested json with Jackson - json

I have a json schema as follows
{
"student" : {
"first name" : "abc",
"last name" : "efg"
"age" : 10,
"sex" : "m",
"subjects" : [
{"name" : "Math", "marks" : 10}.
{"name" : "Science", "marks" : 10}
]
}
}
I am trying to deserialize this into the following class structure :
class Student {
Map<String, Object> studentAttributes;
#JsonProperty("subjects")
List<Map<String, Object> subjects
}
When i try the jackson deserializer the subject attribute (from json) gets mapped into studentAttributes of the java class as string
Any suggestions ?

Related

How to define the json schema for array of json objects in claimcenter

How to define the json schema for array of json objects .
How to write schema for this json example
example :
[
{
"name" : "amy",
"Age" : "25"
},
{
"name" : "john",
"Age" : "20"
}
]
Tried in different ways but not working.

F# Define Types for Json with nested list

Follow up question to this question, to parse json to deedle dataframe.
My json includes some list with nested lists:
apiResponse = {"data":
{"Shipments":
{"ErrorMessage":null,
"Success":true,
"ValidationResult":null,
"TotalCount":494,
"Data":[
{
"CompletedDate":"2021-04-12T10:13:13.436Z",
"ItemId":"dd4520bb-aa0a-...",
"Organization":{
"OrganizationId":"cac43a32-1f08-...",
"OrganizationName":"XXX"
},
"ShipmentContent" : [
{
"MaterialId": "cac43a32-1f08-..",
"unit": "kg",
"quantity": 2.0,
"labels" : ["A1", "A2", "A3"]
},
{
"MaterialId": "cac43333-1f08-",
"unit": "t",
"quantity": 0.4,
"labels" : ["B1", "B2", "B3"]
}
]
},
{......,
....}]}}}
My code so far:
type ApiTypes =
{
ItemId : Guid
CompletedDate : Nullable<DateTime>
Organization:
{|
OrganizationId : Guid
OrganizationName : string
|}
ShipmentContent : // ? How to define the List
{|
MaterialId : Guid
Quantity : Nullable<decimal>
Unit : string
Labels: List // ?
|}
}
How can I define these types? The next step would be:
let jsonObject = JObject.Parse(graphResponse)
let frame =
jsonObject.["data"].["Shipments"].["Data"].Children()
|> Seq.map (fun jtok -> jtok.ToObject<ApiTypes>())
|> Frame.ofRecords
Can I define all in one type, or do I have to define a seperate type for ShipmentContents?
I realy apreciate your help!
Fiddle here (doesn't work, but for sharing the code)
This should work if you want to have it all in one type:
type ApiTypes =
{
ItemId : Guid
CompletedDate : Nullable<DateTime>
Organization:
{|
OrganizationId : Guid
OrganizationName : string
|}
ShipmentContent :
{|
MaterialId : Guid
Quantity : Nullable<decimal>
Unit : string
Labels: string[]
|}[]
}
Note that I've defined the lists as arrays, since arrays are the collection type supported by JSON.

Can't serialize Json to Java object using Jackson ObjectMapper

I'm writing a Java spring boot mvc application with possibility of data export / import. I wrote a wrapper class, that shoud serialize / deserialize data for Student class. It works good for export, but during import an error appears
com.fasterxml.jackson.databind.exc.MismatchedInputException: Root name
'student' does not match expected ('students') for type [simple type,
class org.bajiepka.courseApp.wrappers.Response] at [Source:
(FileInputStream); line: 2, column: 3]
here is my maven jackson dependency:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
I use wrapper class Response for list of students,
package org.bajiepka.courseApp.wrappers;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRootName;
import org.bajiepka.courseApp.domain.Student;
#JsonRootName("import")
public class Response {
private Iterable<Student> students;
#JsonProperty("students")
public Iterable<Student> getStudents(){
return students;
}
public void setStudents(Iterable<Student> students) {
this.students = students;
}
}
And this is my Student class:
#Data
#Entity
public class Student {
private #Id #GeneratedValue Long id;
private #Version int version;
#NotNull
private String name;
private String address;
private String phone;
private Integer gradeBook;
private float averageProgress;
public Student() {}
}
}
This is the method that created an export file:
public String write(boolean toFile){
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
ObjectWriter writer = mapper.writer().withDefaultPrettyPrinter();
try {
String result = writer.writeValueAsString(response);
if (toFile){
result = fileService.writeToFile(result);
}
return result;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return "";
}
after export i get the file with json, that i can't convert to java objects:
{
"student" : [ {
"id" : 1,
"version" : 0,
"name" : "Rachel Jessica Parker",
"address" : "Pentaho",
"phone" : "111-22-33",
"gradeBook" : 1000121,
"averageProgress" : 0.0
}, {
"id" : 2,
"version" : 0,
"name" : "Bobby Jackson Junior",
"address" : "Illinois",
"phone" : "222-33-44",
"gradeBook" : 1000122,
"averageProgress" : 0.0
}, {
"id" : 3,
"version" : 0,
"name" : "Sammy Smith Carlson",
"address" : "Pennsylvania",
"phone" : "333-44-55",
"gradeBook" : 1000123,
"averageProgress" : 0.0
}, {
"id" : 4,
"version" : 0,
"name" : "Harry Dale Harrison",
"address" : "Detroit",
"phone" : "444-55-66",
"gradeBook" : 1000124,
"averageProgress" : 0.0
}, {
"id" : 5,
"version" : 0,
"name" : "Lindsey jefferson Conly",
"address" : "Washington",
"phone" : "555-66-77",
"gradeBook" : 1000125,
"averageProgress" : 0.0
}, {
"id" : 6,
"version" : 0,
"name" : "Mo Williams Jr.",
"address" : "New York",
"phone" : "666-77-88",
"gradeBook" : 1000126,
"averageProgress" : 0.0
} ]
}
And finally this is the method for conversion:
#GetMapping(value = "/import")
public String importFile(#RequestParam Long id){
File importFile = new File(exchangeFileService.findById(id).getName());
if (importFile.exists()) {
try (FileInputStream stream = new FileInputStream(importFile)) {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
TypeReference<Response> typeReference = new TypeReference<>(){};
Response response = mapper.readValue(stream, typeReference);
} catch (IOException e) {
e.printStackTrace();
}
}
return "redirect:/exchange/upload";
}
i get mentioned above MismatchInputException at mapper.readValue(stream, typeReference)
ObjectMapper should return me a Response with a list of students but it doesn't...
#UPDATE
I've managed to find the cause of the error.
During the Object -> Json serialization jackson root name is missed...
I've added manually
{
**"import" : {**
"student" : [ {
"id" : 1,
"version" : 0,
"name" : "Rachel Jessica Parker",
"address" : "Pentaho",
"phone" : "111-22-33",
"gradeBook" : 1000121,
"averageProgress" : 0.0
}, ... ]
,
"course" : [ {
"id" : 7,
"version" : 0,
"name" : "Physics for 9-th grade",
"number" : 100292910,
"cost" : 25000.0,
"modules" : 0,
"max_COURSES_PER_STUDENT" : 3,
"modules_PER_COURSE" : 10
}, ... ]
**}**
}
Also i've managed to extend Response class, as it was required... Now i'm trying to find the reason in ObjectMapper during serialization...
The problem was caused due to Java object -> Json serialization without root level.
To add it to Json i've just added it at mapper by withRootName() method and everything works well from now on!
mapper.writer().withDefaultPrettyPrinter().withRootName("import")

Convert Json - Integers without quotes, Strings with quotes

I'm reading a CSV file with some strings and some integer columns and converting them to JSON. While this conversion, all fields and values seem to have double quotes around them. However I want the integer values NOT to have double quotes.
I'm using Jackson Fasterxml and here's my code snippet
File input = new File("/Users/name/1.csv");
File output = new File("/Users/name/output.json");
CsvSchema csvSchema = CsvSchema.builder().setUseHeader(true).build();
CsvMapper csvMapper = new CsvMapper();
// Read data from CSV file
List<Object> readAll = csvMapper.readerFor(Map.class).with(csvSchema).readValues(input).readAll();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonGenerator.Feature.QUOTE_NON_NUMERIC_NUMBERS, true);
// Write JSON formated data to output.json file
mapper.writerWithDefaultPrettyPrinter().writeValue(output, readAll);
Here's my expected output: Output, please note id and budget do not have double quotes on them
[ {
"id" : 120,
"name" : "Name 1",
"type" : "type1",
"budget" : 100
},
{
"id" : 130,
"name" : "Name 2",
"type" : "type2",
"budget" : 200
},
{
"id" : 140,
"name" : "Name 3",
"type" : "type2",
"budget" : 130
},
{
"id" : 150,
"name" : "Name 4",
"type" : "type4",
"budget" : 400
}
}]
However all fields and values have quotes after conversion
[ {
"id" : "120",
"name" : "Name 1",
"type" : "type1",
"budget" : "100"
},
{
"id" : "130",
"name" : "Name 2",
"type" : "type2",
"budget" : "200"
},
{
"id" : "140",
"name" : "Name 3",
"type" : "type2",
"budget" : "130"
},
{
"id" : "150",
"name" : "Name 4",
"type" : "type4",
"budget" : "400"
}
}]
Unfortunately right now it is not possible to read CSV and specify type for using schema only. You can create POJO with private int budget; and conversion will be done automatically. For other solutions take a look on this question: jackson-dataformat-csv: Mapping number value without POJO where you can see:
Usage of univocity-parsers
Trick with custom Map implementation.

Jmeter - How to remove id from given json

I'm comparing 2 jsons with JSR223 Assertion and I'm willing to remove the ids from all levels from the response json:
{
"id" : 52906,
"name1" : "559812 Company name1",
"name2" : "559812 Company name2",
"country" : "DE",
"interests" : {
"id" : 848675,
"description" : false
},
"emails" : [ {
"id" : 904881,
"address" : "559812#gmail.com"
} ],
...
I'm using the following Groovy code:
def slurper2 = new JsonSlurper();
def jsonResponse = slurper2.parseText(prev.getResponseDataAsString());
jsonResponse.rows.findAll { it.remove("id") };
But it doesn't work - Please advise.
I don't really understand where you got this rows bit as I don't see any JSON Array named "rows" in your response.
If you want to remove all "id" attributes you can use the following approach:
def response = prev.getResponseDataAsString()
def responseWithoutIds = response.replaceAll("\"id\"[ ]*:[^,}\\]]*[,]?", "")
// do what you need with the modified response, i.e. store it into a JMeter Variable
vars.put("responseWithoutIds", responseWithoutIds)
Demo:
References:
String.replaceAll() method JavaDoc
Pattern class JavaDoc
Apache Groovy - Why and How You Should Use It
import groovy.json.*;
def s='''{
"id" : 52906,
"name1" : "559812 Company name1",
"name2" : "559812 Company name2",
"country" : "DE",
"interests" : {
"id" : 848675,
"description" : false
},
"emails" : [ {
"id" : 904881,
"address" : "559812#gmail.com"
} ]
}
'''
def removeAttr(node, attr){
if(node instanceof Map){
node.remove(attr)
node.each{ k,v-> removeAttr(v, attr) }
}else if(node instanceof List){
node.each{ i-> removeAttr(i, attr) }
}
}
def slurper2 = new JsonSlurper();
def jsonResponse = slurper2.parseText(s);
removeAttr(jsonResponse,"id")
println JsonOutput.prettyPrint(JsonOutput.toJson(jsonResponse))