Jackson custom value for nested class's field - java

Good day everyone,
Im struggling with serializing object with nested object having custom name with # JsonProperty.
So, here it is:
public class Wrapper {
public final Payload payload;
public Wrapper(String name){
this.payload = new Payload(name);
}
public static final class Payload{
#JsonProperty("customName")
public final String name;
#JsonCreator
public Payload(#JsonProperty ("customName") String name){
this.name = name;
}
}
}
So, in every test I see non-custom name - "name". I added getter with #JsonProperty without any success.
My test class:
#JsonTest
public class SerializeWrapperTest {
#Test
void whenSerialiseThanCorrect() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
Wrapper wrapper =
new Wrapper("name");
String json = objectMapper.writeValueAsString(wrapper);
Assertions.assertEquals("{"payload":{"customName":"name"}}",json);
}
}
Test results:
Expected :{"payload":{"customName":"name"}}
Actual :{"payload":{"name":"name"}}
org.opentest4j.AssertionFailedError.
Edited.

If I understood it correct , you need to have a custom property in json for the field , "name".
For that you need to do following -
public class Wrapper {
public final Payload payload;
public Wrapper(String name){
this.payload = new Payload(name);
}
public static final class Payload{
#JsonProperty("customName")
public final String name;
public Payload(String name){
this.name = name;
}
}
JUnit -
public class WrapperTest {
#Before
public void setUp() throws Exception {
}
#After
public void tearDown() throws Exception {
}
#Test
public void whenSerialiseThanCorrect() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
Wrapper wrapper =
new Wrapper("Ajeet");
String json = objectMapper.writeValueAsString(wrapper);
System.out.println(json);
}
}
}

Related

List<Long> is not serialised to String in Java

We have a class Agent with assignedUsers as List<Long>
when we try to convert the object as JSON document, we are using ObjectMapper writeValueAsString method, which does not serialize the ids into String instead the key assignedUsers are not missed in the JSON string.
import java.io.IOException;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Agent {
private List<Long> assignedUserIds;
private String name;
private static final String json = "{\"name\":\"New Agency\", \"assignedUserIds\":[23,24]}";
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public List<Long> gocuetAssignedUserIds() {
return assignedUserIds;
}
public void setAssignedUserIds(final List<Long> assignedUserIds) {
this.assignedUserIds = assignedUserIds;
}
public static void main(String[] args) {
Agent agencyInfo = null;
try {
agencyInfo = new ObjectMapper().readValue(json, Agent.class);
System.out.println("Built Agent :: " + new ObjectMapper().writeValueAsString(agencyInfo)); // Outputs: Built Agent :: {"name":"New Agency"}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Your getter for the field assignedUserIds is called gocuetAssignedUserIds(). This is why it's not serialized (the mapper does not recognize it), either mark it with the annotiation #JsonGetter("assignedUserIds") or rename it to getAssignedUserIds() to match the field.

Serializing static nested class members on XStream

I have an application that uses XStream to serialize and deserialize classes to XML. It works great. I got a question whether static inner classes are serializable. Per the XStream's FAQs, it can. However, a Test class that has a nested static class doesn't seem like serializing the data.
public static class TestInner
{
public static String param1;
public static String param2;
public static String getParam1()
{
return param1;
}
public static void setParam1(final String param1)
{
TestInner.param1 = param1;
}
public static String getParam2()
{
return param2;
}
public static void setParam2(final String param2)
{
TestInner.param2 = param2;
}
}
final XStream xstream = new XStream();
final TestInner inner = new Test.TestInner();
inner.setParam1("valueparam1");
inner.setParam2("valueparam2");
logger.info("{}", xstream.toXML(inner));
Yields,
<test.Test_-TestInner/>
Is this a known behavior or limitation of XStream?
Tested using the Xstream tutorial (which is fairly the same as the code you gave) and is working [the difference between your code and mine is my variables are not static] and I think that is the reason. Used the following dependency as well
package com.stackoverflow;
public class TestRunnerOuter {
public static class TestRunner{
private String name;
public TestRunner() {}
public TestRunner(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
and then ->
XStream xstream = new XStream();
TestRunner inner = new TestRunnerOuter.TestRunner();
inner.setName("Test");
System.out.println(xstream.toXML(inner));
dependency->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.11.1</version>
</dependency>
output ->
<com.stackoverflow.TestRunnerOuter_-TestRunner>
<name>Test</name>
</com.stackoverflow.TestRunnerOuter_-TestRunner>

Jackson deserialize an array of object to pojo

So i have this JSON file
{
"results":[
"result":{},
"result":{}
]
}
I wish to deserialize it to a java object which contains an array of result objects.
public class Foo(){
#JsonProperty("results")
private Result[] results;
public void setResults(Result[] results){
this.results = results;
}
public Result[] getResults(){
return this.results;
}
}
public class JsonToObject(){
ObjectMapper mp = new ObjectMapper();
public void createObject(String jsonFile){
Foo bar = mp.readValue(jsonFile, Foo.Class)
}
}
My issue is I keep getting deserialization issues as I have not definied "result".
One way I can get around this is to have result as a class variable inside Result but that seems stupid to do and also may cause issues with re-serializing.
How can I convert the JSON so that my class contains an array of result?
Your question program is wrong. There are many problems with your code. Please use below sample:
public class Foo {
#JsonProperty("results")
private Result[] results;
public Foo() {
}
public Result[] getResults() {
return results;
}
public void setResults(Result[] results) {
this.results = results;
}
}
public class Result {
private String name;
public Result() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static void main(String[] args) throws IOException {
ObjectMapper mp = new ObjectMapper();
String content = "{\"results\":[{\"name\":\"apple\"},{\"name\":\"lemon\"}]}";
Foo bar = mp.readValue(content, Foo.class);
}

accept multiple JSON formats in web service

In my REST web service I need to accept JSON that can have two different structures.
Currently I have:
#Path("/")
public class MyAppResource {
...
#Context private HttpServletRequest request;
...
#POST
#Produces(MediaType.APPLICATION_JSON)
public MyResponseItem check(MyRequestItem body) {
...
}
}
where
public class MyRequestItem {
...
#JsonCreator
public MyRequestItem(#JsonProperty("data") ArrayList<TextItem> data) {
...
}
...
}
and
class TextItem {
...
#JsonCreator
public TextItem(#JsonProperty("count") int count,
#JsonProperty("text") String text) {
...
}
...
}
So it accepts JSON of the form {"data":[{"count":123,"text":"abc"},...]}.
In addition to the above format I need to accept this format: {"data":["abc",...]}. That is, I think I need to change TextItem so that it can either be a String or a class as above.
How to achieve this?
If you don't mind it to be the same class for both cases(TextItem), the easiest option for you is to add 1 more TextItem constructor with single string argument.
Here is demo:
public class Main {
public static String json1 = "{\"data\":[{\"count\":123,\"text\":\"abc\"}]}";
public static String json2 = "{\"data\":[\"abc\"]}";
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.readValue(json1, MyRequestItem.class));
System.out.println(mapper.readValue(json2, MyRequestItem.class));
}
#Data // lombok.Data;
#ToString // lombok.ToString;
public static class MyRequestItem {
private List<TextItem> data;
#JsonCreator
public MyRequestItem(#JsonProperty("data") ArrayList<TextItem> data) {
this.data = data;
}
}
#Data
#ToString
public static class TextItem {
private int count;
private String text;
#JsonCreator
public TextItem(#JsonProperty("count") int count,
#JsonProperty("text") String text) {
this.count = count;
this.text = text;
}
// this is the only thing you need to add to make it work
public TextItem( String text) {
this.text = text;
}
}
}
Result:
MyRequestItem(data=[TextItem(count=123, text=abc)])
MyRequestItem(data=[TextItem(count=0, text=abc)])

Issue With #JsonProperty on Method

I currently have my POJO class as such for deserializing a json source.
public class OpenBuilding extends Building {
#JsonProperty("BuildingPostCode")
#Override
public String getPostcode() {
return super.getPostcode();
}
}
Where the parent class is as such
public abstract class Buidling {
protected String postcode;
public String getPostcode() {
return this.postcode;
}
}
My issue is that the String postcode isn't getting mapped at all. It works when using the annotation on the field. However since it is an inherited field and I have other children of Building, which use different property names for the same data, I cannot have it implemented in that way.
For example:
public class DirectedBuilding extends Building {
#JsonProperty("Pseudo_PostCode")
#Override
public String getPostcode() {
return super.getPostcode();
}
}
Perhaps try defining a constructor with #JsonCreator.
class Parent {
private final String foo;
public Parent(final String foo) {
this.foo = foo;
}
public String getFoo() {
return foo;
}
}
class Child extends Parent {
#JsonCreator
public Child(#JsonProperty("foo") final String foo) {
super(foo);
}
#JsonProperty("foo")
public String getFoo() {
return super.getFoo();
}
}
public static void main(String[] args) throws Exception {
final ObjectMapper objectMapper = new ObjectMapper();
final Child toSerialize = new Child("fooValue");
// Serialize the object to JSON
final String json = objectMapper.writer()
.withDefaultPrettyPrinter()
.writeValueAsString(toSerialize);
// Prints { "foo" : "fooValue" }
System.out.println(json);
// Deserialize the JSON
final Child deserializedChild = objectMapper.readValue(json, Child.class);
// Prints fooValue
System.out.println(deserializedChild.getFoo());
}

Categories

Resources