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?
4 Answers
Answers 1
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.
Answers 2
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.
Answers 3
I believe that it is not possible with Jackson, The workarounds that I can think of are
Split it into 2 object
Teacher
andStudent
. You can still pass the same object twice but with different classesTeacher
andStudent
, It works, but what about theid
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, } }
Answers 4
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.
0 comments:
Post a Comment