Jersey Marshalling Member List Issue - java

I'm using Java Jersey 1.x to marshall an object that has several members, one of which is a list. All member variables are getting marshalled properly and returned with the correct return type. However, it doesn't include the objectList in the return data.
Example:
#XmlRootElement
public class ClassWithList {
private String front;
private int total;
private ArrayList<AnotherPOJOObject> objectList;
...
getters/setters
Getter:
public List<AnotherPOJOObject> getObjectList() {
return objectList;
}
I debugged it and checked that objectList is indeed populated with data.
AnotherPOJOObject is also annotated as an XmlRootElement

Have a look at http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/XmlAccessorType.html . It details how JAXB will attempt to serialize POJOs. In particular note that it defaults to public members only - which means that "Every public getter/setter pair and every public field will be automatically bound to XML, unless annotated by XmlTransient". In this case I'm guessing that you don't have a public setter field for objectList so JAXB won't serialize it. To get the list to serialize you could:
Add a public setter method for objectList
Declare objectList as public (probably not a good idea)
Add an #XmlElement annotation to the getter to explicitly tell JAXB to marshal the list to XML.

I had faced the same issue and solved after some trial and error.
Try giving the annotation #XmlElementWrapper(name = "orders") to getObjectList() and also make the type to private List<AnotherPOJOObject> objectList;

Thanks to the suggestion to basiljames, I was able to get closer to the answer. The real issue was that the List of AnotherPOJOOject wasn't so plain after all. Each object had an untyped Map of it's own, and that threw the Marshaller into a fit, because, it always wants to know the type of an object.
I guess the takeaway from this answer to make sure that every collection you return has a well defined type!

Related

Why can’t Jackson deserialize single field class with RequiredArgsConstructor?

If I have a class using Lombok:
#RequiredArgsConstructor
#Getter
class Example {
private final String id;
}
And try to deserialize it from
{
“id”: “test”
}
Jackson throws an exception that although at least one creator was provided, it could not deserialize.
If I then add another final String field to that class, and add that field to the JSON, it is deserialized with no complaints.
Does anyone know what’s going on here? Why are you unable to deserialize if you only have one field?
When only way to intialize object properties is through contructor, Jackson needs to be told that deserialization should happen using constructor via #JsonCreator annotation.
Also, all the property names should be provided via #JsonProperty annotation because Jackson needs to know the sequence of attributes passed in contructor to correctly map json values to Java object attributes.
So, if you are not using lombok contructor, then constructor will look like
#JsonCreator
public Example (#JsonProperty("id") String id) {
this.id = id;
}
If you don't want to manually write the contructor, go ahead with #tashkhisi's answer.
Also, I highly doubt following could happen. Could you update the question with code showing this?
If I then add another final String field to that class, and add that field to the JSON, it is deserialized with no complaints.

Can I ignore a getter-based write-only property during deserialization in Java Jackson?

I have a legacy JSON API class that I'm evolving to remove a certain property. It's currently at a point where the property value is always the same constant, so I would like my Java code to be just a simple getter with no underlying field for it. I want to continue serializing the value until I know that all my clients have migrated off of using the value. The object is only read by my clients, so I don't have to worry about them sending other values across.
public class MyType {
private String value;
public boolean isLegacyValue() {
return true;
}
}
That said, I don't want any test code or the like to fail if I deserialize a full value with the now-constant property. Is there a way I can tell Jackson to serialize a setter method-only property, but ignore it on deserialization? I tried a few different things, but I get a UnrecognizedPropertyException on deserialization. I'd rather not change the global DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES just for this one property.
{"value": "ABC", "legacyValue": true}
Also acceptable would be a way to tell Jackson to include the value without including a Java field for it.
I'm aware I can add a getter in addition to my setter, or make it a field, but both those options feel like they're confusing the Java API, as it's not actually matching the constant constraint:
public void setLegacyValue(boolean legacyValue) {
// No-op; only exists for Jackson deserialization
}
One thing I've found to work through trial and error is making it a final field. For whatever reason, Jackson knows to handle that as a write-only constant in a way that doesn't work with the getter without matching setter. This will be my solution if there's no way to do it with just a getter.
private final boolean legacyValue = true;
public boolean isLegacyValue() {
return legacyValue;
}
Jackson supports "one-way" properties using the access parameter of #JsonProperty. Annotate your property like this:
#JsonProperty(access = READ_ONLY)
public boolean isLegacyValue() {
return true;
}

How to cast Jest SearchResult hits to domain object

I am using Jest to query Elasticsearch and so far it has been great. Jest's documentation says:
Result can be cast to List of domain object;
... and shows this example:
SearchResult result = client.execute(search);
List<SearchResult.Hit<Article, Void>> hits = searchResult.getHits(Article.class);
// or
List<Article> articles = result.getSourceAsObjectList(Article.class);
getSourceAsObjectList is deprecated, and I am using:
List<SearchResult.Hit<ImmutableConceptDocument, Void>> concepts = result.getHits(ImmutableConceptDocument.class);
... Where ImmutableConceptDocument is an immutables generated class - otherwise pretty straight forward POJO, with attributes named as I see under the source of my search results.
However, when I use the above line, I don't get the source properties mapped, I do get other details like score, type, index etc. mapped.
What am I missing? Does the domain class need to have specific Jest annotations or something like that?
I can't see any good examples in the unit tests too. This one maps to Object.class and that does not show me a mapping example.
Here is the immutable class:
#Value.Immutable
public abstract class EsConceptDocument {
public abstract String term();
public abstract Category type();
public abstract List<String> synonyms();
}
... where Category is an enum type.
As Val pointed out in the comments, this was because immutables.io makes the generated class' constructor private (and exposes a builder).
I removed immutable from this class and wrote a constructor and getters and it worked.

Java Jersey use GET to return JSON that returns only some fields instead of all

Does naybody knows a way to use Jersey's GET method to return a JSON that returns only some fields of an entity instead of all?
Does anybody know a way to use Jersey's GET method to return a JSON that returns only some fields of an entity instead of all?
E.g. in the following class I want to receive (with POST) values for 'name' and for 'confidential', buy while returning (with GET) I only need 'name' value, not 'confidential'.
#Entity
#Table(name = "a")
#XmlRootElement
#JsonIgnoreProperties({"confifentialInfo"})
public class A extends B implements Serializable {
private String name;
#Basic(optional = false)
private String confifentialInfo;
// more fields, getters and setters
}
If you are using the JAXB approach, you can mark fields with #XmlTransient to omit them. If you are using POJO mapping or want to exclude fields only for some requests, you should construct the JSON with the low level JSON API.
If you are using Jackson, you can use the annotation #JsonIgnore for methods
Marker annotation similar to javax.xml.bind.annotation.XmlTransient
that indicates that the annotated method is to be ignored by
introspection-based serialization and deserialization functionality.
That is, it should not be consider a "getter", "setter" or "creator".
And #JsonIgnoreProperties for properties
Annotation that can be used to either suppress serialization of
properties (during serialization), or ignore processing of JSON
properties read (during deserialization).

How to make Jersey/Jackson serialize empty list; single element list as an array

Using Jersey and Jackson to create a REST interface, how do I get List fields to be serialized as a list when there are 0 or 1 elements in them. For example:
#XmlRootElement(name="foo")
public class Foo {
#XmlElement
public List<Bar> getBars() {
return this.bars;
}
}
#Path("foo")
public FooResource {
#GET
public Foo getFoo() {
return theFoo;
}
}
When bars has no elements, the result serializes as null and when it contains a single element, it serializes as that element, not an array containing a single element. Is there a way to get these to always serialize as an array?
For reference, I'm using Jersey 1.10 and Jackson 1.9.2.
I am pretty sure that you are not actually using Jackson ("POJO" variant of JSON serialization), since Jackson would not convert single-element arrays or lists to anything else. So you are probably using one of legacy output methods (like jettison); meaning that if you configure system to use POJO mapping it should just work.
I wrote a blog post ages ago about forcing Jersey to serialize single element arrays correctly, not sure if it's out-dated now (its from mid-2010!), but it might be of use.
Note the blog comment from Brill Pappin on the blog demonstrating a different approach which means upgrading the Jettison library that you are using.
In short you can write a custom JaxbContextResolver that looks a little like:
#Provider
#Component
public class JAXBContextResolver implements ContextResolver {
private JAXBContext context;
public JAXBContextResolver() throws Exception {
MappedBuilder builder = JSONConfiguration.mapped();
builder.arrays("invite");
builder.rootUnwrapping(true);
this.context = new JSONJAXBContext(builder.build(), Payload.class);
}
public JAXBContext getContext(Class objectType) {
return (Payload.class.equals(objectType)) ? context : null;
}
}
For clarity, my payload class looked a little like
#XmlRootElement(name = "response")
#XmlAccessorType(XmlAccessType.FIELD)
public class Payload {
#XmlElement(name = "invite")
List invites;
... etc.
Regarding stopping Jackson serializing bean properties as null, see my previous answer here, about using annotations to change that behaviour.
I managed to solve JSON array "bug" in recent Jersey json library (v1.14 Sep 2012). Secret ingredient is JSONConfiguration and ContextResolver magic. See my following post it has a full code example, customized ContextResolver and rest Application class might be somewhat fuzzy logic in first look.
How to serialize Java primitives using Jersey REST
Primitives and zero or single-element List array are properly serialized to JSON document.
Yes, we also faced the same issue. Jackson cannot serialize list with 0 or single element to json array. So we tried to use Json's ObjectMapper to convert POJO object to String. It will serialize java List to json array irrespective of number of elements in List (0 or 1 or > 0). The code would look like :
request = new ObjectMapper().writeValueAsString(pojo);
where request is of type Object. This will not affect response. You can give a try.

Categories

Resources