I was using JPA AttributeConverter with Spring Boot 1.2.1 RELEASE and it worked fine. But I get the following error after upgrading to Spring Boot 1.3.0.RELEASE
attributeLabelMap.java:
I want to add this as the json format
metadata: {
masked: true,
maxLength: 200,
formula: "a + b",
parentCode: "strAttr_1",
currency: "$",
},
I added this column in entity class
#Column(name = "metadata_json",columnDefinition = "json")
#Convert(converter = HashMapConverter.class)
private Map<String,Object> metaDataAttribute
HashMapConverter class:
package in.nobroker.hood.crm.entity;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import javax.persistence.AttributeConverter;
import java.io.IOException;
import java.util.Map;
#Slf4j
public class HashMapConverter implements AttributeConverter<Map<String, Object>, String> {
private final ObjectMapper objectMapper = new ObjectMapper();
#Override
public String convertToDatabaseColumn(Map<String, Object> stringObjectMap) {
String attributeInfoJson = null;
try {
attributeInfoJson = objectMapper.writeValueAsString(stringObjectMap);
} catch (final JsonProcessingException e) {
log.error("JSON writing error", e);
}
return attributeInfoJson;
}
#Override
public Map<String, Object> convertToEntityAttribute(String s) {
Map<String, Object> attributeInfo = null;
try {
attributeInfo = objectMapper.readValue(s, Map.class);
} catch (final IOException e) {
log.error("JSON reading error", e);
}
return attributeInfo;
}
}
In Postman:
{
"label": "dateAttr_5",
"id": "f73434ba-bfaa-49f5-9a41-b86715a985f2",
"filter": true,
"inUse": true,
"editable": true,
"mandatory": true,
"priority": 0,
"textOptions": "a,b,c,d",
"type": "DATETIME_FORM_DATA",
"filterType": "ABSOLUTE",
"metaDataAttribute": {
"masked": true,
"maxLength": 200,
"formula": "a + b",
"parentCode": "strAttr_1",
"currency": "$"
}
}
I want to add metaDataAttribute when I hit Postman its giving internal server error:
argument "content" is null
failed to fetch attribute label mappings
argument "content" is null
at com.fasterxml.jackson.databind.ObjectMapper._assertNotNull(ObjectMapper.java:4693)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3401)
at in.nobroker.hood.crm.entity.HashMapConverter.convertToEntityAttribute(HashMapConverter.java:31)
at in.nobroker.hood.crm.entity.HashMapConverter.convertToEntityAttribute(HashMapConverter.java:10)
at org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl.toDomainValue(JpaAttributeConverterImpl.java:45)
at org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter$2.doConversion(AttributeConverterSqlTypeDescriptorAdapter.java:140)
... 186 common frames omitted
Add a null check on String s, in convertToEntityAttribute of HashMapConverter
Related
I am trying to create a JSON using the Jackson Streaming API. I know how to create an array of elements in JSON using Jackson as we have plenty of examples related to it. But I am a bit confused about how to create an array of Objects using it.
Following is the JSON structure that I would like to obtain at the end:
{
"name" : "Batman",
"year" : 2008,
"writers":[
{
"name" : "Nolan",
"age" : 49
},
{
"name" : "Johnathan",
"age" : 35
}
]
}
Following is the code I have:
import org.json.JSONObject;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
public class HelloWorld {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
ByteArrayOutputStream jsonStream = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = mapper.getFactory().createGenerator(jsonStream, JsonEncoding.UTF8);
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("name", "Batman");
jsonGenerator.writeNumberField("year", 2008);
jsonGenerator.writeFieldName("writers");
jsonGenerator.writeStartArray();
// How to to create here objects and add it to the "writers"
// Should I create another JsonGenerator and create objects usign it?
jsonGenerator.writeEndArray();
jsonGenerator.writeEndObject();
jsonGenerator.close();
String jsonData = new String(jsonStream.toByteArray(), "UTF-8");
JSONObject json = new JSONObject(jsonData);
System.out.println(json.toString(4));
}
}
Can someone please guide me on how to create the objects and add them to the array one by one? I am unable to find such an example so posting here.
I would just create a Map to store the data. For the writers, you can call List.of to create an in-line List.
import java.io.*;
import java.util.*;
import com.fasterxml.jackson.databind.*;
public class MovieDataWriter {
public static void main(String[] args) {
Map<String, Object> movieData = createMap(
"name", "Batman",
"year", 2008,
"writers", List.of(
createMap(
"name", "Nolan",
"age", 49
),
createMap(
"name", "Johnathan",
"age", 35
)
)
);
writeToFile(movieData, "target/batman.json");
}
private static void writeToFile(Map<String, Object> data, String filename) {
ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
try {
writer.writeValue(new File(filename), data);
} catch (IOException e) {
e.printStackTrace();
}
}
private static Map<String, Object> createMap(Object ...args) {
Map<String, Object> pairs = new LinkedHashMap<>();
for (int i = 0; i < args.length; i += 2) {
pairs.put(String.valueOf(args[i]), args[i + 1]);
}
return pairs;
}
}
Dependencies
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
batman.json
{
"name" : "Batman",
"year" : 2008,
"writers" : [ {
"name" : "Nolan",
"age" : 49
}, {
"name" : "Johnathan",
"age" : 35
} ]
}
After trying a few things I was able to get it. Basically, I had to do the same thing which I was asked in the question. I am not sure why it did not work the first time maybe I missed something. Anyways here is how you can add objects into the array using the Jackson Streaming API. Posting this as it can be beneficial to someone else in the future.
I am creating an array writers in this case and adding the objects into it using the same jsonGenerator.
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.json.JSONObject;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
public class HelloWorld {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
ByteArrayOutputStream jsonStream = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = mapper.getFactory().createGenerator(jsonStream, JsonEncoding.UTF8);
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("name", "Batman");
jsonGenerator.writeNumberField("year", 2008);
jsonGenerator.writeFieldName("writers");
jsonGenerator.writeStartArray();
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("name", "Nolan");
jsonGenerator.writeNumberField("age", 45);
jsonGenerator.writeEndObject();
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("name", "Johanathan");
jsonGenerator.writeNumberField("age", 35);
jsonGenerator.writeEndObject();
jsonGenerator.writeEndArray();
jsonGenerator.writeEndObject();
jsonGenerator.close();
String jsonData = new String(jsonStream.toByteArray(), "UTF-8");
JSONObject json = new JSONObject(jsonData);
System.out.println(json.toString(4));
}
}
You will get the output something like this:
{
"year": 2008,
"name": "Batman",
"writers": [
{
"name": "Nolan",
"age": 45
},
{
"name": "Johanathan",
"age": 35
}
]
}
So I'm used to getting JSON objects from a given API/endpoint, e.g.:
{
"count": 5,
"results": [
{
"example": "test",
"is_valid": true
},
{
"example": "test2",
"is_valid": true
}
]
}
And in a custom deserializer that extends com.fasterxml.jackson.databind.deser.std.StdDeserializer, I know I can use the JsonParser object like so to get the base node to work off of, i.e.:
#Override
public ResultExample deserialize(JsonParser jp, DeserializationContext ctxt) {
JsonNode node = jp.getCodec().readTree(jp);
JsonNode count = node.get("count");
// code to put parsed objects into a ResultExample object...
}
However, I just encountered an API that simply returns an array of JSON objects, e.g.:
[
{
"example": "test",
"is_valid": true
},
{
"example": "test2",
"is_valid": true
},
]
So, I don't believe I can just parse this the same way as before. What would be the correct way to parse this using Jackson?
This may help you:
import java.io.IOException;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
String json = "[\r\n" + " {\r\n" + " \"example\": \"test\",\r\n" + " \"is_valid\": true\r\n"
+ " },\r\n" + " {\r\n" + " \"example\": \"test2\",\r\n" + " \"is_valid\": true\r\n"
+ " }\r\n" + "]";
Example[] ex = mapper.readValue(json, Example[].class);
}
}
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({ "example", "is_valid" })
class Example {
#JsonProperty("example")
private String example;
#JsonProperty("is_valid")
private Boolean isValid;
public String getExample() {
return example;
}
#JsonProperty("example")
public void setExample(String example) {
this.example = example;
}
#JsonProperty("is_valid")
public Boolean getIsValid() {
return isValid;
}
#JsonProperty("is_valid")
public void setIsValid(Boolean isValid) {
this.isValid = isValid;
}
}
When response is a JSON Object you can use default bean deserialiser. In case it is a JSON Array you can read it as array and create response object manually. Below you can find example custom deserialiser and BeanDeserializerModifier which is used to register custom deserialiser. BeanDeserializerModifier allows to use default deserialiser when JSON payload fits POJO model:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerBase;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.CollectionType;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
SimpleModule module = new SimpleModule();
module.setDeserializerModifier(new BeanDeserializerModifier() {
#Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
if (beanDesc.getBeanClass() == Response.class) {
return new ResponseJsonDeserializer((BeanDeserializerBase) deserializer);
}
return super.modifyDeserializer(config, beanDesc, deserializer);
}
});
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
System.out.println(mapper.readValue(jsonFile, Response.class));
}
}
class ResponseJsonDeserializer extends BeanDeserializer {
private final BeanDeserializerBase baseDeserializer;
protected ResponseJsonDeserializer(BeanDeserializerBase src) {
super(src);
this.baseDeserializer = src;
}
#Override
public Response deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
if (p.currentToken() == JsonToken.START_OBJECT) {
return (Response) baseDeserializer.deserialize(p, ctxt);
}
if (p.currentToken() == JsonToken.START_ARRAY) {
CollectionType collectionType = ctxt.getTypeFactory().constructCollectionType(List.class, Item.class);
JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(collectionType);
List<Item> results = (List<Item>) deserializer.deserialize(p, ctxt);
Response response = new Response();
response.setCount(results.size());
response.setResults(results);
return response;
}
throw MismatchedInputException.from(p, Response.class, "Only object or array!");
}
}
class Response {
private int count;
private List<Item> results;
// getters, setters, toString
}
class Item {
private String example;
#JsonProperty("is_valid")
private boolean isValid;
// getters, setters, toString
}
Above code for JSON Object payload prints:
Response{count=5, results=[Item{example='test', isValid=true}, Item{example='test2', isValid=true}]}
And for JSON Array payload prints:
Response{count=2, results=[Item{example='test', isValid=true}, Item{example='test2', isValid=true}]}
Guess I should have just written the unit test before asking the question, but apparently you can just do it the same way. Only difference is the base node is a JsonArray which you have to iterate over. Thanks everyone who looked into this.
I am writing in java
I have a json containing an array, and I am trying to split the array (flattening), each element in the array , should be independent.
I am using org.json.JSONObject library for parsing the json (but can use also other class)
example:
{
"key": "123456",
"date": "2018-01-01",
"users": [
{"name": "jim", "age": 20},
{"name": "jack", "age": 21}
]
}
result:
[
{
"key": "123456",
"date": "2018-01-01",
"users": {"name": "jim", "age": 20}
},
{
"key": "123456",
"date": "2018-01-01",
"users": {"name": "jack", "age": 21}
}
]
is there any ready library for that?
edit:
I am looking for a solution which is generic, the json could have different fields, and the only thing I know is the path to the arrar (users in the example)
You can solve it using almost any available JSON parsing library. For example I will do it with Jackson. You most probably already have data classes (POJOs) for your entries. That's my view of such hierarchy
BaseDataView represents common fields
import java.util.Date;
public abstract class BaseDataView {
protected String key;
protected Date date;
// public get/set
}
OldDataView represents your old view
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class OldDataView extends BaseDataView {
private List<User> users;
public List<User> getUsers() {
return users;
}
#Override
public String toString() {
return "Data [key=" + key + ", date=" + date + ", users=" + users + "]";
}
public List<NewDataView> toNewData() {
if (users != null && !users.isEmpty()) {
return users.stream().map(u -> new NewDataView(key, date, u))
.collect(Collectors.toList());
} else {
return Collections.singletonList(new NewDataView(key, date, null));
}
}
}
NewDataView represents our new view
import java.util.Date;
public class NewDataView extends BaseDataView {
private User users;
public NewDataView() {
super();
}
public NewDataView(String key, Date date, User users) {
super();
this.key = key;
this.date = date;
this.users = users;
}
public User getUsers() {
return users;
}
public void setUsers(User users) {
this.users = users;
}
#Override
public String toString() {
return "NewData [key=" + key + ", date=" + date + ", users=" + users + "]";
}
}
And the main class which will read value, convert it and write to string.
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
public class StackExample {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
String input = "{\"key\": \"123456\",\"date\": \"2018-01-01\",\"users\":"
+ " [{\"name\": \"jim\", \"age\": 20},{\"name\": \"jack\", \"age\": 21}]}";
OldDataView d = mapper.readValue(input, OldDataView.class);
List<NewDataView> nd = d.toNewData();
String ret = mapper.writeValueAsString(nd);
System.out.println(ret);
}
}
This will generate desired result. For sure, you can get rid of NewDataView class if you are ok will additional [] bracers in users field in your JSON representation. You also can use various annotations to customize your format.
Hope it helps!
here is the method I wrote:
import org.json.JSONArray;
import org.json.JSONObject;
public static JSONArray parse(JSONObject json, String key) {
JSONArray flattenedJson = new JSONArray();
JSONArray arr = json.getJSONArray(key);
json.remove(key);
for (int i = 0; i < arr.length(); i++){
JSONObject jscopy = new JSONObject(json.toString()); // cloning the json
jscopy.put(key, arr.get(i));
flattenedJson.put(jscopy);
}
return flattenedJson;
}
using it:
public static void main(String[] args) {
String jsonStr = "{key: 12345 ,date: '2018-01-01', users: [{name: jim, age: 20},{name: jack, age: 21}]}";
JSONObject json = new JSONObject(jsonStr);
JSONArray flattenedJson = parse(json, "users");
System.out.println(flattenedJson.toString());
}
output:
➜ [{"date":"2018-01-01","key":12345,"users":{"name":"jim","age":20}},
{"date":"2018-01-01","key":12345,"users":{"name":"jack","age":21}}]
You have to do a manual parsing for your flatten requirement. I have some improvements to suggest on the parse method in your answer.
Instead of
JSONObject jscopy = new JSONObject(json.toString()); // cloning the json
For cloning the array stripped json, use below:
JSONObject jscopy = new JSONObject(json, JSONObject.getNames(json));
This will be faster and will avoid a serialize/deserialize (in json terms).
You may also evaluate the JSONObject.getNames(json) part before and outside of the for loop, and just use the evaluated String[] inside the loop.
Wanted to covert an xml String to Json and I am doing it as below.
XML which has to be converted
<Item>
<Property name="Description" value="Description 1"/>
<Property name="EffDate" value="01/05/2017"/>
<Property name="ExpDate" value="12/31/9999"/>
<Property name="Status" value="Launched"/>
</Item>
I have created a Class for the xml as below.
public class Context {
#XmlElement(name = "Item")
private List<Item> offer;
}
public class Item {
#XmlElement(name = "Property")
private List<Property> properties;
}
public class Property {
#XmlAttribute
private String name;
#XmlAttribute
private String value;
}
I am using Gson libraries to convert this Java object to Json - g.toJson.
Comverted JSON -
"offer": [{
"properties": [{
"name": "Description",
"value": "Description 1"
},
{
"name": "EffDate",
"value": "01/05/2017"
},
{
"name": "ExpDate",
"value": "12/31/9999"
},
{
"name": "Status",
"value": "Launched"
}]
}]
But we wanted to convert the JSON as below -
"offer": [{
"Description" : "Description 1",
"EffDate":"01/05/2017",
"ExpDate": "12/31/9999",
"Status": "Launched"
}]
Is there a way to convert the properties name and value as Item class properties.?
Try using this link: https://github.com/stleary/JSON-java This is a JSON Helper class that can convert XML to JSON for example:
public class Main {
public static int PRETTY_PRINT_INDENT_FACTOR = 4;
public static String TEST_XML_STRING =
"<?xml version=\"1.0\" ?><test attrib=\"moretest\">Turn this to JSON</test>";
public static void main(String[] args) {
try {
JSONObject xmlJSONObj = XML.toJSONObject(TEST_XML_STRING);
String jsonPrettyPrintString = xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR);
System.out.println(jsonPrettyPrintString);
} catch (JSONException je) {
System.out.println(je.toString());
}
}
}
Hope this helps :)
It is possible using FasterXML library. where you can write your custom logic for generating XML and JSON. By overriding serialize of JsonSerializer class.
Need to write Serializer like :
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class ContextSerializer extends JsonSerializer<Context> {
#Override
public void serialize(Context t, JsonGenerator jg, SerializerProvider sp) throws IOException, JsonProcessingException {
jg.writeStartObject();
jg.writeArrayFieldStart("offer");
for (Item i : t.offer) {
jg.writeStartObject();
for (Property property : i.properties) {
jg.writeStringField(property.name, property.value);
}
jg.writeEndObject();
}
jg.writeEndArray();
jg.writeEndObject();
}
}
For convert:
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBException;
public class Main {
public static void main(String[] args) throws JAXBException, JsonProcessingException {
Context c = new Context();
List<Item> offer = new ArrayList<>();
Item pr = new Item();
pr.properties = new ArrayList<>();
Property p = new Property();
p.name = "asdf";
p.value = "va1";
pr.properties.add(p);
p = new Property();
p.name = "asdf1";
p.value = "va11";
pr.properties.add(p);
offer.add(pr);
c.offer = offer;
try {
SimpleModule module = new SimpleModule();
module.addSerializer(Context.class, new ContextSerializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
objectMapper.setSerializationInclusion(Include.NON_DEFAULT);
String json = objectMapper.writeValueAsString(c);
System.out.println(json);
} catch (Exception e) {
System.out.println(""+e);
}
}
}
O/P JSON : (Provided O/P JSON is wrong in your question if you give the name to the list("offer") then it always inside object link)
{
"offer": [{
"asdf": "va1",
"asdf1": "va11"
}
]
}
Maven Dependency for package is:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0.pr3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0.pr3</version>
</dependency>
If you are using Java 8 or later, you should check out my open source library: unXml. unXml basically maps from Xpaths to Json-attributes.
It's available on Maven Central.
Example
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.nerdforge.unxml.factory.ParsingFactory;
import com.nerdforge.unxml.parsers.Parser;
import org.w3c.dom.Document;
public class Parser {
public ObjectNode parseXml(String xml){
Parsing parsing = ParsingFactory.getInstance().create();
Document document = parsing.xml().document(xml);
Parser<ObjectNode> parser = parsing.obj("/")
.attribute("offer", parsing.arr("/Item")
.attribute("Description", "Property[#name='Description']/#value")
.attribute("EffDate", "Property[#name='EffDate']/#value")
.attribute("ExpDate", "Property[#name='ExpDate']/#value")
.attribute("Status", "Property[#name='Status']/#value")
)
.build();
ObjectNode result = parser.apply(document);
return result;
}
}
It will return a Jackson ObjectNode, with the following json:
{
"offer": [
{
"Status": "Launched",
"Description": "Description 1",
"ExpDate": "12/31/9999",
"EffDate": "01/05/2017"
}
]
}
You may convert xml to a map, modify it and then convert to a json. Underscore-java library has static methods U.fromXml(xml) and U.toJson(json). I am the maintainer of the project.
I've been writing a Rest service using Jackson to extract the name and sizeFromStorage inside the response value.
I created the below classes in an attempt to do this:
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#JsonIgnoreProperties(value = {"status", "header"})
public class Vaults {
private List<Object> response;
public Vaults(){
}
public Vaults(List<Object> response){
this.response = response;
}
public List<Object> getResponse(){
return response;
}
public void setResponse(List<Object> response) {
this.response = response;
}
#Override
public String toString() {
return "" + response;
}
}
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import java.io.InputStream;
public class JacksonObjectModelTest {
public static void main(String[] args) throws IOException {
String jsonFileName = "/JsonRead/json.json";
List<Vaults> emps = new JacksonObjectModelTest().getVaultList(jsonFileName);
System.out.println(emps.toString());
}
public ArrayList<Vaults> getVaultList(String jsonFileName) throws IOException {
//read json file data to String
InputStream inputStream = getClass().getResourceAsStream(jsonFileName);
//create ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
//convert json string to object
CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(List.class, Vaults.class);
ArrayList<Vaults> emps = objectMapper.readValue(inputStream, collectionType);
return (ArrayList<Vaults>) emps;
}
}
{
"status": "ok",
"header": {
"now": 1491545894581,
"status": "ok",
"requestId": "WOcvJsCoAmoAAESbkBYAAAB5"
},
"response": {
"vault": [
{
"id": 20,
"name": "Apple",
"description": "",
"sizeFromStorage": 95957225298,
"storagePools": [
{
"storagePool": {
"id": 1,
"name": "storage-pool1",
"sizeFromStorage": 95957225298,
"generations": [
{
"generation": {
"sequence": 0
}
}
]
}
}
]
},
{
"id": 21,
"name": "Banana",
"description": "",
"sizeFromStorage": 98957268244,
"storagePools": [
{
"storagePool": {
"id": 2,
"name": "storage-pool1",
"sizeFromStorage": 98957268244,
"generations": [
{
"generation": {
"sequence": 0
}
}
]
}
}
]
},
]
}
}
The output I get from this is:
[[{vaults=[{id=20, name=Apple, description=, sizeFromStorage=95957225298, storagePools=[{storagePool={id=1, name=storage-pool1, sizeFromStorage=5043, estimateUsableTotalLogicalSizeFromStorage=95957225298, generations=[{generation={sequence=0}}]}}]}, {id=20, name=Apple, description=, sizeFromStorage=95957225298, storagePools=[{storagePool={id=1, name=storage-pool1, sizeFromStorage=5043, estimateUsableTotalLogicalSizeFromStorage=95957225298, generations=[{generation={sequence=0}}]}}]}]]
However, what I want to do is the name and sizeFromStorage values. So far I've managed to strip out the first three values. Unfortunately I'm now stuck as I'm not very familiar with Rest services or reading JSON. Is there any way I can delve further into the JSON to get what I need or have I approached this in the wrong way?
Additional info:
Since posting my original question I came up with this(based on something I saw on a different site):
package JsonRead;
import java.io.File;
import java.io.IOException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonTreeModel {
public static void main(String[] args) {
try{
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(new File("JsonRead/json.json"));
JsonNode vaultsNode = root.path("response").path("vault");
/*if(vaultsNode.isArray()){
for(JsonNode node : vaultsNode){
String name = node.path("name").asText();
System.out.println("Array Name: " + name);
}
}*/
for(JsonNode node : vaultsNode){
String name = node.path("name").asText();
String bytesUsed = node.path("sizeFromStorage").asText();
System.out.println("Name: " + name + ", Bytes Used: " + bytesUsed);
}
} catch(IOException e){
System.out.println("IO Exception " + e );
}
}
}
It works for what I want but is there a better way to do this?
Will, thanks for the response. I'll look into your suggestion.
Ok, so i just re-read your question.
Recommend creating yourself a VaultDAO object with a more meaningful custom object type to use for the response collections. Prvoided you use the same variable names (which it looks like are known to you) then it should deserialize for you