Repeat json field with different name - java

i have a POJO mapped which i serialize using Jackson
public class Foo{
private String bar;
// public setter and getter for bar
}
it serializes to
{bar:"value"}
is there a jackson annotation to get another field in the JSON with the same value but with a different alias name, something like
{bar:"value", another_bar:"value"}

This should work for duplicating the value, though why you'd want to waste space like that is puzzling:
public class Foo {
private String bar;
#JsonProperty
public String getBar() {
return this.bar;
}
public void setBar(String bar) {
this.bar = bar;
}
#JsonProperty("another_bar")
public String getAnotherBar() {
return this.bar;
}
}

Related

How to deserialize raw JSON to Java object with Jackson

I've got two POJOs:
#lombok.Value
public class Foo {
String foo;
Bar bar;
}
#lombok.Value
public class Bar {
String bar;
String baz;
}
I'd like to be able to deserialize the following to a Foo instance:
{
"foo": "some foo",
"bar": "{ \"bar\": \"some bar\", \"baz\": \"some baz\" }"
}
If I understand it correctly this the exact opposite #JsonRawValue. There, it convert a Java String value (which is valid JSON value) to JSON object. But here, I need to convert a JSON string value to Java object.
I suspect that I need to write a custom deserializer, but I'm not sure how exactly since it involves parsing the raw JSON and assign it to the field. Maybe BeanDeserializerModifier? (I have no idea how to use it.)
I'd like to keep the object immutable (#Value), but I can drop this requirement if it helps solving the problem.
Thanks.
if you use FooDto class delete this Bar bar; from DtoClass
or use this
#lombok.Value
public class Foo {
String foo;
#JsonIgnore
Bar bar;
}
With the help of this question mentioned by #Michał Ziober I managed to do it. Posting it here for reference since it was kinda tricky to get it working (with #Value and CamelCase property naming in JSON):
{
"Foo": "some foo",
"Bar": "{ \"bar\": \"some bar\", \"baz\": \"some baz\" }"
}
And the implementation is:
#Value
#Builder
#JsonDeserialize(builder = Foo.FooBuilder.class)
public class Foo {
#JsonAlias("Foo") // note this!
String foo;
Bar bar;
#JsonPOJOBuilder(withPrefix = "")
public static class FooBuilder {
#JsonAlias("Bar") // note this!
#JsonDeserialize(using = BarDeserializer.class)
public FooBuilder bar(Bar bar) {
this.bar = bar;
return this;
}
}
}
#lombok.Value
public class Bar {
String bar;
String baz;
}
public class BarDeserializer extends StdDeserializer<Bar> {
public BarDeserializer() {
super(Bar.class);
}
#Override
public Bar deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
return (Bar) ((ObjectMapper) p.getCodec()).readValue(p.getValueAsString(), _valueClass);
}
}

Jaxb custom element from two fields of an object

Is there a way with jaxb to create a custom element from two fields from an object?
Here's an example of what I have and what I want. I realize I could extract the fields into a seperate annotated class, but I'm curious of theres a way to do something similar to this.
#XmlRootElement()
public class Foo {
public String bar
public String baz
}
Expected output xml:
<foo>
<customElement bar="barValue">bazValue</customElement>
</foo>
Thanks!
class for foo
#XmlRootElement()
public class Foo {
private customElement CustomElement;
public CustomElement getCustomElement(){
return customElement;
}
#XmlElement
public void setCustomElement(CustomElement customElement){
this.customElement = customElement;
}
}
class for custom element
#XmlAccessorType(XmlAccessType.FIELD)
public class CustomElement {
#XmlAttribute
private String bar;
#XmlValue
private String baz
// set getters and setters
}

Is it possible to use jaxb annotations to navigate objects after they are unmarshalled?

I have a fairly complex XML schema and I use hyperjaxb3 to generate pojo's with annotations for. There are times when I have the parent object and would like to check the value of a child object that may be 8 or 9 children deep. Is there anyway to use jaxb, or another tool, to get a list of child objects of a specific class based on jaxb annotations?
I could write a recursive function to search all children for an instance of a class but that would be less than ideal. Any advise would be appreciated, thanks.
You don't have to write the code to walk the object tree yourself — there are a few out there already (jdereg's java-util for example), and the JAXBIntrospector will find objects annotated with XmlRootElement for you. There would be a little more work required if you're looking for other annotations, but not much.
For example:
public static void main(String[] args) throws JAXBException {
JAXBContext jc = JAXBContext.newInstance(Foo.class);
JAXBIntrospector is = jc.createJAXBIntrospector();
// Found objects
List<Foo.Bar> bars = new ArrayList<>();
// Object name to look for
QName barName = new QName("", "bar");
// Unmarshalled root object to introspect
Foo target = new Foo(new Foo.Bar());
// Walk the object graph looking for "bar" elements
Traverser.traverse(target, o -> {
if (barName.equals(is.getElementName(o))) {
bars.add((Foo.Bar) JAXBIntrospector.getValue(o));
}
});
System.out.println(bars);
}
//
// Some test objects
//
#XmlRootElement(name = "foo")
public class Foo {
private Bar bar;
public Foo() { }
public Foo(Bar bar) {
this.bar = bar;
}
#XmlElement(name="bar")
public Bar getBar() {
return bar;
}
public void setBar(Bar bar) {
this.bar = bar;
}
#XmlRootElement(name="bar")
public static class Bar {
String name = "kate";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "Bar{name='" + name + '\'' + '}';
}
}
}

How to tell Jackson to ignore a field given that there is no condition on the field being null?

[Not a repeat].
I need the exact opposite of JsonIgnore. In my use case there is just one field that I need to add in serialization and all others are to be ignored. I've explored #JsonSerialize, #JsonInclude and #JsonProperty but none work as required by me.
Is there a way to achieve this or I'll need to mark the fields to be ignored with #JsonIgnore?
By default, Jackson will auto-detect all getters in your object and serialize their values. Jackson distinguished between "normal" getters (starting with "get") and "is-getters" (starting with "is", for boolean values). You can disable auto-detection for both entirely by configuring the ObjectMapper like this:
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.AUTO_DETECT_GETTERS);
mapper.disable(MapperFeature.AUTO_DETECT_IS_GETTERS);
Alternatively, you can disable the auto-detection on a per class basis using #JsonAutoDetect. Annotate the fields or getters you actually do want to serialize with #JsonProperty.
#JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
public class MyObject {
private String foo;
#JsonProperty("bar")
private String bar;
private boolean fubar;
public MyObject(String foo, String bar, boolean fubar) {
this.foo = foo;
this.bar = bar;
this.fubar = fubar;
}
public String getFoo() {
return foo;
}
public String getBar() {
return bar;
}
public boolean isFubar() {
return fubar;
}
}
Serializing MyObject like this:
mapper.writeValueAsString(new MyObject("foo", "bar", true));
will result in the following JSON
{"bar":"bar"}
you can try this #JsonIgnoreProperties("propertyName") on the top of variable..

JACKSON JSON deserialization issue with overrloaded setter

From several reasons we have to make for developers convenience be able to set the one reference via overloaded setters ( this due it is modelled as oneOf attribute).
I would expect that depending on the JSON schema the polymorphic (oneOf) property would have the deserialized reference to object of FooType or BarType, ....
depending on the JSON schema.
I was hoping since FooType , BarType follow bean convention they can be easily determined like it happens for JacksonFeature in JAXRS ....
In my dummy test it seems to not work as described below :
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
mapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
mapper.readValue(SCHEMA, SimplePojo.class);
The issue is that the mapper crashes, and JSON schema(SCH1) can not be deserialized to POJO
The JSON schema (SCH1)
{
"dummy" : {
"bar" : "bar",
"baz" : 10
},
"other" : {
"foo" : "hi there"
},
"simple" : "simple"
}
The sub element types dummy, other look like :
public class BarType {
private String bar;
private Number baz;
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
public Number getBaz() {
return baz;
}
public void setBaz(Number baz) {
this.baz = baz;
}
and
public class FooType {
private Object foo;
public Object getFoo() {
return foo;
}
public void setFoo(Object foo) {
this.foo = foo;
}
The top level POJO ( i skipped some part )
public class SimplePojo {
private String simpleField;
private Object dummyField;
private Object otherField;
public String getSimple() {
return simpleField;
}
public void setSimple(String simple) {
this.simpleField = simple;
}
...
public void setDummy(final FooType dummy) {
this.dummyField = dummy;
}
public void setDummy(final BarType dummy) {
this.dummyField = dummy;
}
public void setDummy(final String dummy) {
this.dummyField = dummy;
}
the issue is that i can not deserialize correctly the schema (SCH1), instead I receive the :
com.fasterxml.jackson.databind.JsonMappingException: Conflicting setter definitions for property "dummy": com.hybris.api.poc.SimplePojo#setDummy(1 params) vs com.hybris.api.poc.SimplePojo#setDummy(1 params)
I was trying to use the #JsonCreator, and #JsonDeserialize but no luck it seems that i can not have two (non primitive) override setters
#JsonDeserialize( builder = FooType.FooTypeBuilder.class)
#JsonCreator
public void setDummy(final FooType dummy) {
this.dummyField = dummy;
}
/**
* Type specific setter for #dummy;
*
* #param dummy a reference to be set for #dummy
*/
#JsonDeserialize( builder = BarType.BarTypeBuilder.class )
#JsonCreator
public void setDummy(final BarType dummy) {
this.dummyField = dummy;
}
Can you hint me where I should the solution or am i breaking some principal concept ?
I do think you are breaking some principal concept there. For this type of scenario, having a base abstract class with JsonTypeInfo and JsonSubTypes annotations to describe your sub-object would probably be preferred. If you absolutely need the ability to set the three types via setDummy(...), would this work for you?
Replace:
public void setDummy(final FooType dummy) {
this.dummyField = dummy;
}
public void setDummy(final BarType dummy) {
this.dummyField = dummy;
}
public void setDummy(final String dummy) {
this.dummyField = dummy;
}
With:
#JsonDeserialize( using = DummyDeserializer.class )
public void setDummy(final Object dummy) {
// If you really need to restrict to the three types, throw exception here
if (! (dummy instanceof FooType || dummy instanceof BarType || dummy instanceof String) ) {
throw new Exception("Cannot setDummy dummy!");
}
this.dummyField = dummy;
}
This would require you to do the deserialization manually for all three classes in your DummyBuilder, but should solve your multi-setters problem. I've not tried to implement this, but think it works.
No, without inheritance structure Jackson has no way of automatically determining intended type during deserialization. If they did share the same base type, you could use #JsonTypeInfo to indicate how type id is included (usually as a property); and have a single setter (or creator property).
Otherwise you can not have conflicting setters (i.e. more than one with types that are not related to each other by sub-typing).

Categories