I have a sample dummy JSON response that looks like :
{
"id": 1,
"teacher_name": "Foo",
"teacher_address": "123 Main St.",
"teacher_phone_num": 1234567891,
"student_name": "Bar",
"student_address": "546 Main St.",
"student_phone_num": 9184248576
}
The above is a silly example, but it helps illustrate the issue I am having trying to de-serialize the above into a Java class called "Employee" using Jackson:
public class Employee {
String name;
String address;
String phoneNumber;
}
The issue is that the JSON has two different prepends so I cannot annotate each field in Employee and have the object mapper map teacher_name and student_name to the name field in an Employee object. Is there a way in Jackson to specify two differently named nodes to map to the same Java field?
So in my example, I should end up with two Employee objects (I am guaranteed to have one pair per response)
It is not possible with Jackson. It is designed to map one-to-one: one json object to one java object. But you want to end up with two java objects from one json.
I would recommend you to go with strait forward way by implementing some processing level that will consume Response and map it to two Employee objects.
I think you need to write code to do the mapping whether you use annotation or not.
Simple is the best.
If you read the json as JsonNode it should be trivial to code the assignments.
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class Q44094751 {
public static void main(String[] args) throws IOException {
String json = "{\"id\": 1," +
"\"teacher_name\": \"Foo\", \"teacher_address\": \"123 Main St.\", \"teacher_phone_num\": 1234567891," +
"\"student_name\": \"Bar\", \"student_address\": \"546 Main St.\", \"student_phone_num\": 9184248576" +
"}";
ObjectMapper mapper = new ObjectMapper();
// Read
JsonNode node = mapper.readValue( json, JsonNode.class);
Employee teacher = new Employee(),
student = new Employee();
teacher.name = node.get( "teacher_name" ).toString();
teacher.address = node.get( "teacher_address" ).toString();
teacher.phoneNumber = node.get( "teacher_phone_num" ).toString();
student.name = node.get( "student_name" ).toString();
student.address = node.get( "student_address" ).toString();
student.phoneNumber = node.get( "student_phone_num" ).toString();
// Check
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
System.out.println( mapper.writeValueAsString( teacher ) );
}
public static class Employee {
String name;
String address;
String phoneNumber;
}
}
Given a "silly example", the answer that may looks silly.
For example if you have a hundred properties, a loop with reflection should work better.
If you have requirement(s) that is not reflected in the example,
please edit your question to better describe the actual problem(s) you are facing.
I believe that it is not possible with Jackson, The workarounds that I can think of are
Split it into 2 object Teacher and Student. You can still pass the same object twice but with different classes Teacher and Student, It works, but what about the id field?
Make a Java class similar to JSON.
If you would like to make it more meaning full structure then use this structure
{
"id": 1,
"teacher" :{
"name": "Foo",
"address": "123 Main St.",
"phone_num": 1234567891,
},
"student" :{
"name": "Bar",
"address": "546 Main St.",
"phone_num": 9184248576,
}
}
You may use #JsonUnwrapped annotation to unwrap the employee's properties inline in parent object. This annotation also provides the option to specify the prefix name of which will be used while ser/der the object.
Below is your example:
public static class Employee {
private String name;
private String address;
#JsonProperty("phone_num")
private String phoneNumber;
// setter / getter removed from brevity
}
public static class YourJsonObject {
private int id;
#JsonUnwrapped(prefix="teacher_")
private Employee teacher;
#JsonUnwrapped(prefix = "student_")
private Employee student;
// setter / getter removed from brevity
}
Now Configure the ObjectMapper to use the appropriate naming strategy( from your example,I see snake case strategy is desired)
Test Case:
#Test
public void peformTest() throws Exception {
final String inputJson = "{\n" +
" \"id\": 1,\n" +
" \"teacher_name\": \"Foo\",\n" +
" \"teacher_address\": \"123 Main St.\",\n" +
" \"teacher_phone_num\": 1234567891,\n" +
" \"student_name\": \"Bar\",\n" +
" \"student_address\": \"546 Main St.\",\n" +
" \"student_phone_num\": 9184248576\n" +
" }";
ObjectMapper mapper = new ObjectMapper();
// important one
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
// read your json as object
YourJsonObject myObject = mapper.readValue(inputJson, YourJsonObject.class);
assertThat(myObject.getTeacher().getName(), is("Foo"));
assertThat(myObject.getStudent().getName(), is("Bar"));
}
Hope this helps.
Related
I am trying to unmarshal the following JSON
[{
"myId": "12851cb3087f51b4fb392b1fea36eef9508",
"secondaryId": "787CFD4A-6B1D-4415-AD56-D075B535B890",
"my_key": "keyABCD",
"email": ""
}, {
"myId": "12851cb3087f51b4fb392b1fea36eef9508",
"secondaryId": "BFACD2F0-F5EF-4F05-AA6B-00E18CA907EF",
"my_key": "keyABCD",
"email": ""
}, {
"myId": "12851cb3087f51b4fb392b1fea36eef9508",
"secondaryId": "567DE8C0-B5B5-4961-B97A-A2DD374AEED1",
"my_key": "keyABCD",
"email": ""
}, {
"myId": "12851cb3087f51b4fb392b1fea36eef9508",
"secondaryId": "78a52d90-be6c-4d80-b79d-0e256028ba01",
"my_key": "keyABCD",
"email": "test#email.com"
}, {
"myId": "12851cb3087f51b4fb392b1fea36eef9508",
"secondaryId": "aeb148e7-fc88-4a71-8baa-63b6528e463e",
"my_key": "keyABCD",
"email": ""
}]
and already have a bufferreader (myBufferedReader) which has the above json. POJO
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
#ToString
#AllArgsConstructor
public class MyPOJO {
#Getter #Setter private String myId;
#Getter #Setter private String secondaryId;
#Getter #Setter private String my_key;
#Getter #Setter private String email;
}
On using below mapper -
ObjectMapper mapper = new ObjectMapper();
List<MyPOJO> eventList = mapper.readValue(myBufferedReader.readLine(),mapper.getTypeFactory().constructCollectionType(List.class, MyPOJO.class));
getting error. Please help. - (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
If above is not the correct way, please suggest the best way to read from bufferreader and create list of pojo class mapped with json.
Regards,
Dan
Add your default constructor, empty constructor, by adding #NoArgConstructor top of your POJO class.
Then simply convert your buffer reader JSON string to a list of POJO like this:
List<MyPOJO> eventList = mapper.readValue(myBufferedReader, new TypeReference<List<MyPOJO>>(){});
Well, I am not a Master of all things Java JSON. I have a tool which I use whenever I need to parse JSON. Be aware that there are multiple tools for parsing JSON String's, but I am only going to post the solution for the version that I use. I, personally, do not get into Java's Component Annotations because they add such a tremendous amount of complexity, and do not add anything to value of the code. I am not here to prove my points, but I don't get into Java Beans.
There is a library called the GSON Library that (supposedly) can map JSON String's directly to Java Object's (POJO's as you called them). I am, unfortunately, unfamiliar with the GSON Tool, and it might actually be able to "automatically" build a class MyPOJO using Annotations as you have requested.
Here is my solution, which just uses the standard JSON Parsing Library which I call javax.json.* below. You would have to retrieve the JSON JAR by looking for it using a Google Search.
import java.io.*;
import javax.json.*;
public class S
{
// I am just going to create the class for parsing this
// If there is a GSON way to do this "Automatically", then you
// should not use this Answer I have written to Stack Overflow
public static class MyPOJO
{
public final String myId;
public final String secondaryId;
public final String myKey;
public final String email;
public MyPOJO(String myId, String secondaryId, String myKey, String email)
{ this.myId=myId; this.secondaryId=secondaryId; this.myKey=myKey; this.email=email; }
public String toString()
{
return
"myId: " + myId + '\n' +
"seoondaryId: " + secondaryId + '\n' +
"myKey: " + myKey + '\n' +
"email: " + email + "\n\n";
}
}
public static void main(String[] argv) throws IOException
{
// This reads the 'input.json' file into the Json parser using
// a simple java.io.FileReader
Reader r = new FileReader("input.json");
// This reads the file, and retrieves the JsonArray that you
// have provided in your original post.
JsonArray ja = Json
.createReader(r)
.readArray();
for (JsonObject jo : ja.getValuesAs(JsonObject.class))
{
String myId = jo.getString("myId");
String secondaryId = jo.getString("secondaryId");
String myKey = jo.getString("my_key");
String email = jo.getString("email");
// What *I* would do is to get rid of the Component Annotation, and simply
// use a Constructor. I don't strongly believe in Java's Annotation Classes,
// and I never use them. If you can find an AUTOMATED WAY to do all of this,
// YOU SHOULD ... - if you are willing to learn it all.
// I HAVE NOT! :)
// If there is an easy way to **DIRECTLY MAP** a JSON Object to a specified
// class - and I believe that the GSON library is capable of directly mapping
// JSON Object's to GSON Java POJO's (Java Object's), but I have not used them
// before. My own personal belief is that if it were easier, then learning the
// GSON JAR Library and Java Documentation (JavaDoc) for GSON.
// Here, though, a Constructor is what I would prefer myself.
MyPOJO mp = new MyPOJO(myId, secondaryId, myKey, email);
System.out.println(mp.toString());
}
}
}
The following is output by the above class to the Shell Terminal:
#cloudshell:~$ java S
myId: 12851cb3087f51b4fb392b1fea36eef9508
seoondaryId: 787CFD4A-6B1D-4415-AD56-D075B535B890
myKey: keyABCD
email:
myId: 12851cb3087f51b4fb392b1fea36eef9508
seoondaryId: BFACD2F0-F5EF-4F05-AA6B-00E18CA907EF
myKey: keyABCD
email:
myId: 12851cb3087f51b4fb392b1fea36eef9508
seoondaryId: 567DE8C0-B5B5-4961-B97A-A2DD374AEED1
myKey: keyABCD
email:
myId: 12851cb3087f51b4fb392b1fea36eef9508
seoondaryId: 78a52d90-be6c-4d80-b79d-0e256028ba01
myKey: keyABCD
email: test#email.com
myId: 12851cb3087f51b4fb392b1fea36eef9508
seoondaryId: aeb148e7-fc88-4a71-8baa-63b6528e463e
myKey: keyABCD
email:
I have a java class representing a JSON using Jackson. All of the fields, with one exception, can be translated using no annotations at all. 1-to-1, simple translations (although some of them are nested POJOs).
#Data
#AllArgsConstructor
#NoArgsConstructor
public class MyPojo {
private String someString;
private AnotherPojo someOtherPojo;
//The problem child:
private Object value;
}
The field value which is an exception to this rule, can represent any JSON field matching value* where * is a wildcard of indefinite length. That means valueString or valueReference in JSON will be assigned to this field with the assertion that only one may be present.
{
"someString": "asdasdadasdsa",
"someOtherPojo": {
"someOtherProperty": "whatever"
},
"valueCodeableConcept": {
"text": "text value",
"coding": [
{
"code": "my-code"
}
]
}
}
Using a custom deserializer on the top-level class, I can scrape all of the fields from the root node (baseNode in the following example) that start with value and set the value field appropriately. That works great! However, in doing so, I now have to set every other field in this MyPojo class manually in my deserializer, and I have to put a custom copy of this deserializer on each POJO that uses a field like value*.
private Object parseValueX(JsonNode baseNode, DeserializationContext context) throws IOException {
//Find the concrete implementation referred to by the value[x] field
Set<String> concreteNames = new HashSet<>();
baseNode.fieldNames().forEachRemaining(name -> {
if (name.startsWith("value")) {
concreteNames.add(name);
}});
if (concreteNames.isEmpty()) {
return null;
}
if (concreteNames.size() > 1) {
throw JsonMappingException.from(context, "The field value[x] must have no more than one concrete " +
"implementation, ex: valueCode, valueCodeableConcept, valueReference");
}
String concreteName = concreteNames.stream().findFirst().orElseThrow(() -> new RuntimeException(""));
JsonNode jsonSource = baseNode.get(concreteName);
//...deserialize from jsonSource, solved, but not relevant to question...
}
To make this apply to any value* property on any POJO, I tried to move the deserializer to the value attribute in the POJO (whereas it's on the top-level resource now). The first flaw is that the deserializer isn't even invoked unless the JSON property exactly matches value. What I actually need is for the entire parent JSON resource to be passed to that field-specific deserializer, so that I may find the matching field and assign it -- OR -- I need to be able to have the deserializer on MyPojo only assign the one field value and allow the automatic deserialization to take care of the others. How do I do either of these?
For those curious about my motivation, I am implementing the HL7 FHIR Specification, which specifies generic attributes called value[x] (here's one example: https://www.hl7.org/fhir/extensibility.html#Extension) where [x] becomes the type of the resource.
I think a good fit for you problem is #JsonAnySetter. This method annotation tells Jackson to route unknown properties to it. the arg (in your case) is a Map containing the json tree of the unknown property. if I understand your code properly, the name of the value property contains the class name of the target Pojo. so once you have a class name, you can tell Jackson how to "deserialize" the map into an instance of the target class.
Here is an example based on the code from the question
public class MyPojo {
public String someString; // made properties into public for this example...
public AnotherPojo someOtherPojo;
public Object value;
#JsonAnySetter
public void setValue(String name, Object value) {
System.out.println(name + " " + value.getClass());
System.out.println(value);
// basic validation
if (name.startsWith("value") && value instanceof Map) {
String className = "com.company." + name.substring("value".length());
System.out.println(name + " " + value.getClass() + " " + className);
System.out.println(value);
try {
// nice of Jackson to be able to deserialize Map into Pojo :)
ObjectMapper mapper = new ObjectMapper();
this.value = mapper.convertValue(value, Class.forName(className));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(this.value + " " + this.value.getClass());
}
}
}
public class AnotherPojo {
public String someOtherProperty;
}
public class CodeableConcept {
public String text;
public Code[] coding;
}
public class Code {
public String code;
}
I am trying to store a JSON object in MySQL database in spring boot. I know I am doing something wrong but I a can't figure out what it is because I am fairly new to Spring.
I have a rest endpoint where I get the following JSON object (via HTTP PUT) and I need to store it in database so that the user can fetch it later (via HTTP GET).
{
"A": {
"Name": "Cat",
"Age": "1"
},
"B": {
"Name": "Dog",
"Age": "2"
},
"C": {
"Name": "Horse",
"Age": "1"
}
}
Note that in the above case The number of keys in the object may vary, Due to that requirement I am using a HashMap to catch the object in the controller.
#RequestMapping(method = RequestMethod.POST)
public String addPostCollection(#RequestBody HashMap<String, Animal> hp) {
hp.forEach((x, y) -> {
postRepository.save(hp.get(x));
});
return "OK";
}
As you can see in the method, I can iterate the HashMap and persist each Animal object in db. But I am looking for a way to persist the entire HashMap in a single record. I have did some reading and they suggest me to use a #ManyToMany mapping.
Can anyone point me in a direction to persist the HashMap in a different way? (or is using the #ManyToMany the only and right way to do this?)
Maven dependency
The first thing you need to do is to set up the following Hibernate Types Maven dependency in your project pom.xml configuration file:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
Domain model
Let's assume you have the following entity:
#Entity(name = "Book")
#Table(name = "book")
#TypeDef(
typeClass = JsonType.class,
defaultForType = JsonNode.class
)
public class Book {
#Id
#GeneratedValue
private Long id;
#NaturalId
private String isbn;
#Column(columnDefinition = "jsonb")
private JsonNode properties;
//Getters and setters omitted for brevity
}
Notice the #TypeDef is used to instruct Hibernate to map the JsonNode object using the JsonType offered by the Hibernate Types project.
Testing time
Now, if you save an entity:
Book book = new Book();
book.setIsbn( "978-9730228236" );
book.setProperties(
JacksonUtil.toJsonNode(
"{" +
" \"title\": \"High-Performance Java Persistence\"," +
" \"author\": \"Vlad Mihalcea\"," +
" \"publisher\": \"Amazon\"," +
" \"price\": 44.99" +
"}"
)
);
entityManager.persist( book );
Hibernate is going to generate the following SQL statement:
INSERT INTO
book
(
isbn,
properties,
id
)
VALUES
(
'978-9730228236',
'{"title":"High-Performance Java Persistence","author":"Vlad Mihalcea","publisher":"Amazon","price":44.99}',
1
)
And you can also load it back and modify it:
Session session = entityManager.unwrap( Session.class );
Book book = session
.bySimpleNaturalId( Book.class )
.load( "978-9730228236" );
LOGGER.info( "Book details: {}", book.getProperties() );
book.setProperties(
JacksonUtil.toJsonNode(
"{" +
" \"title\": \"High-Performance Java Persistence\"," +
" \"author\": \"Vlad Mihalcea\"," +
" \"publisher\": \"Amazon\"," +
" \"price\": 44.99," +
" \"url\": \"https://www.amazon.com/High-Performance-Java-Persistence-Vlad-Mihalcea/dp/973022823X/\"" +
"}"
)
);
Hibernate taking caare of the UPDATE statement for you:
SELECT b.id AS id1_0_
FROM book b
WHERE b.isbn = '978-9730228236'
SELECT b.id AS id1_0_0_ ,
b.isbn AS isbn2_0_0_ ,
b.properties AS properti3_0_0_
FROM book b
WHERE b.id = 1
-- Book details: {"price":44.99,"title":"High-Performance Java Persistence","author":"Vlad Mihalcea","publisher":"Amazon"}
UPDATE
book
SET
properties = '{"title":"High-Performance Java Persistence","author":"Vlad Mihalcea","publisher":"Amazon","price":44.99,"url":"https://www.amazon.com/High-Performance-Java-Persistence-Vlad-Mihalcea/dp/973022823X/"}'
WHERE
id = 1
You can use FasterXML (or similar) to parse the Json into an actual object (you need to define the class) and use Json.toJson(yourObj).toString() to retrieve the Json String. It also simplifies working with the objects since your data class may also have functionality.
Your JSON is well structered, so usually theres no need to persist the entire map in one single record. You won't be able to use the Hibernate/JPA query functions and a lot more.
If you really want to persist the entire map in one single record, you could persist the map in its string representation and, as already proposed, use a JSON parser like Jackson to rebuild your HashMap
#Entity
public class Animals {
private String animalsString;
public void setAnimalsString(String val) {
this.animalsString = val;
}
public String getAnimalsString() {
return this.animalsMap;
}
public HashMap<String, Animal> getAnimalsMap() {
ObjectMapper mapper = new ObjectMapper();
TypeReference<HashMap<String,Animal>> typeRef = new TypeReference<HashMap<String,Animal>>() {};
return mapper.readValue(animalsString, typeRef);
}
}
Your animal class:
public class Animal {
private String name;
private int age;
/* getter and setter */
/* ... */
}
And you could change your controller method to
#RequestMapping(method = RequestMethod.POST)
public String addPostCollection(#RequestBody String hp) {
Animals animals = new Animals();
animals.setAnimalsString(hp);
animalsRepository.save(hp);
return "OK";
}
One animal is one record. You are saving more records, not one record. You can commit more records in one transaction.
See: How to persist a lot of entities (JPA)
Is there any way in Gson to map multiple JSON fields to a single Java object member variable?
Let's say I have a Java class...
public class MyClass {
String id;
String name;
}
I want to use this single class with two different services. However, these two services differ in how they return their data...
{ "id": 2341, "person": "Bob" }
... and ...
{ "id": 5382, "user": "Mary" }
... respectively.
Is there any way to map both the "person" and "user" fields in the JSON string to the name field in the Java object?
(Note: I only ever need to convert from JSON string to Java object - never the other way around.)
In October 2015, Gson version 2.4 (changelog) added the ability to use alternate/multiple names for #SerializedName when deserializing. No more custom TypeAdapter needed!
Usage:
java
#SerializedName(value="name", alternate={"person", "user"})
kotlin
#SerializedName(value="name", alternate= ["person", "user"])
https://www.javadoc.io/doc/com.google.code.gson/gson/2.6.2/com/google/gson/annotations/SerializedName.html
for Kotlin fans
#SerializedName(value="name", alternate= ["person", "user"])
It is not supported to define multiple #SerializedName annotations to a field at Gson.
Reason: By default Deserialization is managed with a LinkedHashMap and the keys are defined by incoming json's field names (not the custom class's field names or the serializedNames) and there is a one to one mapping. You can see the implementation(how deserialization works) at ReflectiveTypeAdapterFactory class's inner class Adapter<T>'s read(JsonReader in) method.
Solution:
You can write a custom TypeAdapter which handles name, person and user json tags and maps them to name field of your custom class MyClass:
class MyClassTypeAdapter extends TypeAdapter<MyClass> {
#Override
public MyClass read(final JsonReader in) throws IOException {
final MyClass myClassInstance = new MyClass();
in.beginObject();
while (in.hasNext()) {
String jsonTag = in.nextName();
if ("id".equals(jsonTag)) {
myClassInstance.id = in.nextInt();
} else if ("name".equals(jsonTag)
|| "person".equals(jsonTag)
|| "user".equals(jsonTag)) {
myClassInstance.name = in.nextString();
}
}
in.endObject();
return myClassInstance;
}
#Override
public void write(final JsonWriter out, final MyClass myClassInstance)
throws IOException {
out.beginObject();
out.name("id").value(myClassInstance.id);
out.name("name").value(myClassInstance.name);
out.endObject();
}
}
Test case:
String jsonVal0 = "{\"id\": 5382, \"user\": \"Mary\" }";
String jsonVal1 = "{\"id\": 2341, \"person\": \"Bob\"}";
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(MyClass.class, new MyClassTypeAdapter());
final Gson gson = gsonBuilder.create();
MyClass myClassInstance0 = gson.fromJson(jsonVal0, MyClass.class);
MyClass myClassInstance1 = gson.fromJson(jsonVal1, MyClass.class);
System.out.println("jsonVal0 :" + gson.toJson(myClassInstance0));
// output: jsonVal0 :{"id":5382,"name":"Mary"}
System.out.println("jsonVal1 :" + gson.toJson(myClassInstance1));
// output: jsonVal1 :{"id":2341,"name":"Bob"}
Examples about TypeAdapters.
Edit 2016.04.06 : As #Mathieu Castets has written at his answer, it is supported now. (That is the correct answer for this question.)
public abstract String[] alternate
Returns: the alternative names of
the field when it is deserialized Default: {}
For KOTLIN i used below but doesn't work
#SerializedName(value="name", alternate= ["person", "user"])
so i edited it and here it works fine!!
#SerializedName(value="name", alternate= arrayOf("person", "user"))
I have a JSON string:
{
"fruit": {
"weight":"29.01",
"texture":null
},
"status":"ok"
}
...that I am trying to map back into a POJO:
public class Widget {
private double weight; // same as the weight item above
private String texture; // same as the texture item above
// Getters and setters for both properties
}
The string above (that I am trying to map) is actually contained inside an org.json.JSONObject and can be obtained by calling that object's toString() method.
I would like to use the Jackson JSON object/JSON mapping framework to do this mapping, and so far this is my best attempt:
try {
// Contains the above string
JSONObject jsonObj = getJSONObject();
ObjectMapper mapper = new ObjectMapper();
Widget w = mapper.readValue(jsonObj.toString(), Widget.class);
System.out.println("w.weight = " + w.getWeight());
} catch(Throwable throwable) {
System.out.println(throwable.getMessage());
}
Unfortunately this code throws an exception when the Jackson readValue(...) method gets executed:
Unrecognized field "fruit" (class org.me.myapp.Widget), not marked as ignorable (2 known properties: , "weight", "texture"])
at [Source: java.io.StringReader#26c623af; line: 1, column: 14] (through reference chain: org.me.myapp.Widget["fruit"])
I need the mapper to:
Ignore the outer curly brackets ("{" and "}") altogether
Change the fruit to a Widget
Ignore the status altogether
If the only way to do this is to call the JSONObject's toString() method, then so be it. But I'm wondering if Jackson comes with anything "out of the box" that already works with the Java JSON library?
Either way, writing the Jackson mapper is my main problem. Can anyone spot where I'm going wrong? Thanks in advance.
You need to have a class PojoClass which contains (has-a) Widget instance called fruit.
Try this in your mapper:
String str = "{\"fruit\": {\"weight\":\"29.01\", \"texture\":null}, \"status\":\"ok\"}";
JSONObject jsonObj = JSONObject.fromObject(str);
try
{
// Contains the above string
ObjectMapper mapper = new ObjectMapper();
PojoClass p = mapper.readValue(jsonObj.toString(), new TypeReference<PojoClass>()
{
});
System.out.println("w.weight = " + p.getFruit().getWeight());
}
catch (Throwable throwable)
{
System.out.println(throwable.getMessage());
}
This is your Widget Class.
public class Widget
{ private double weight;
private String texture;
//getter and setters.
}
This is your PojoClass
public class PojoClass
{
private Widget fruit;
private String status;
//getter and setters.
}