Jackson adds backslash in json - java

I'm building REST service on Jersey and using Jackson to produce JSON from java classes of my model. Model with absolutely simple values, I think this is the most typical case. But I get strange result:
[{\"name\":\"Nick\",\"role\":\"admin\",\"age\":\"32\",\"rating\":47}]
My expecting result:
[{"name":"Nick","role":"admin","age":"32","rating":47}]
My source values of fields does NOT contains any special characters. These are simple words.
There're my Java classes.
Entity:
public class User {
private String name;
private String role;
private String age;
private Integer rating;
Class of rest service:
#ServiceConfig(contextName = "myContext")
#Path("/myrest")
public class MyRestService {
private static final String JSON_CONTENT_TYPE = MediaType.APPLICATION_JSON + ";charset=UTF-8";
#Context
protected HttpServletResponse response;
#GET
#Path("/users")
#OpenTransaction
#Produces({MediaType.APPLICATION_JSON})
public String findUsers(#QueryParam("department") String department) {
response.setContentType(JSON_CONTENT_TYPE);
PDTResponse.status(response).sendStatus(Response.Status.OK.getStatusCode());
List<User> users = new ArrayList<>();
users.add(new User("Nick", "admin", "32", 47));
String jsonInString;
ObjectMapper mapper = new ObjectMapper();
try {
jsonInString = mapper.writeValueAsString(users);
} catch (JsonProcessingException ex) {
jsonInString = "thrown exception: " + ex.getMessage();
}
return jsonInString;
}
I've tried to use annotation #JsonRawValue for string properties:
#JsonRawValue
private String name;
But result in this case was:
[{\"name\":Nick,\"role\":admin,\"age\":32,\"rating\":47}]
And I expect:
[{"name":"Nick","role":"admin","age":"32","rating":47}]
It's obvious that Jackson somehow escapes the quotes in result json of response. But why does it do it, and most importantly how to avoid that? By themselves they are just strings! Without any quotes or special characters.
I use Java 7 and Jackson 2.6.1. And Postman to test result.
Any ideas for fix of my problem?

You can configure the ObjectMapper:
final ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
String jsonUsers = mapper.writeValueAsString(users);
more info here

All strings in java have to escape quotes in them. So jsonInString should have slashes in it. When you output jsonInString though it shouldn't have the quotes. Are you looking at it in a debugger or something?

Do this.
ObjectMapper mapper = new ObjectMapper();
mapper.getFactory().setCharacterEscapes(new JsonUtil().new CustomCharacterEscapes());
ObjectWriter writer = mapper.writer();
String jsonDataObject = mapper.writeValueAsString(configMap);
public class CustomCharacterEscapes extends CharacterEscapes {
private final int[] _asciiEscapes;
public CustomCharacterEscapes() {
_asciiEscapes = standardAsciiEscapesForJSON();
//By default the ascii Escape table in jackson has " added as escape string
//overwriting that here.
_asciiEscapes['"'] = CharacterEscapes.ESCAPE_NONE;
}
#Override
public int[] getEscapeCodesForAscii() {
return _asciiEscapes;
}
#Override
public SerializableString getEscapeSequence(int i) {
return null;
}
}

If you are using Spring and the #ControllerAdvice for JSONP, then create a wrapper for the JSON string and use #JsonRawValue on the property. The JSONP #ControllerAdvice will not wrap a String response, it needs an Object.
public class JsonStringResponse {
#JsonValue
#JsonRawValue
private String value;
public JsonStringResponse(String value) {
this.value = value;
}
}
#GetMapping
public ResponseEntity<JsonStringResponse> getJson() {
String json = "{"id":2}";
return ResponseEntity.ok().body(new JsonStringResponse(json));
}
#ControllerAdvice
public class JsonpControllerAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpControllerAdvice() {
super("callback");
}
}
Response is a json object {"id":2}
If there is a callback parameter the response is callbackparameter({"id":2});

Looks like you are over complicating your JAX-RS resource class.
To use Jackson as a JSON provider for Jersey 2.x, you don't need to create an ObjectMapper instance like that. There's a better way to achieve it. Keep reading for more details.
Adding Jackson module dependencies
To use Jackson 2.x as your JSON provider you need to add jersey-media-json-jackson module to your pom.xml file:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.25.1</version>
</dependency>
Registering the Jackson module
Then register the JacksonFeature in your Application / ResourceConfig subclass:
#ApplicationPath("/api")
public class MyApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(JacksonFeature.class);
return classes;
}
}
#ApplicationPath("/api")
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(JacksonFeature.class);
}
}
If you don't have an Application / ResourceConfig subclass, you can register the JacksonFeature in your web.xml deployment descriptor. The specific resource, provider and feature fully-qualified class names can be provided in a comma-separated value of jersey.config.server.provider.classnames initialization parameter.
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.jackson.JacksonFeature</param-value>
</init-param>
The MessageBodyWriter provided by Jackson is JacksonJsonProvider. For more details on how to use Jackson as a JSON provider, have a look at this answer. If you need to customize the ObjectMapper, refer to this answer.
Fixing your resource class
By using the approach described above, you resource class can be as simple as:
#Path("/users")
public class MyRestService {
#GET
#Produces({MediaType.APPLICATION_JSON + ";charset=UTF-8"})
public List<User> findUsers() {
List<User> users = new ArrayList<>();
users.add(new User("Nick", "admin", "32", 47));
return Response.ok(users).build();
}
When requesting such endpoint, it will give you the expected JSON as result.

I have also the same problem and tried different solutions, but non works. The problem is not with the mapper, but with the input to the mapper. As in your case:
jsonInString = mapper.writeValueAsString(users); 'users' is a collection. You need to convert each user to JSONObject, add it to JSONArray and then use the mapper on the array: like this
JSONArray users = new JSONArray();
for (Collection user : usersCollection) {
JSONObject user = new JSONObject(mapper.writeValueAsString(user));
users.put(user);
}
mapper.writeValueAsString(user));

I don't know why, but in my case it works doing this :
private static final String COOKIE_TEMPLATE = "{0}={1};Version={2};Domain={3};Max-Age={4};Path='/'";
response.addHeader("Set-Cookie", MessageFormat.format(COOKIE_TEMPLATE, cookie.getName(),cookie.getValue(), cookie.getVersion(), cookie.getDomain(),Integer.toString(cookie.getMaxAge())));
return ResponseEntity.ok(...);
cookie is a javax.servlet.http.Cookie, and cookie.getValue() contains a string produced by
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(obj);
If I use
response.addCookie(cookie)
I have a resulting cookie definition as JSON with backslashes.
But, if I use
response.addHeader("Set-Cookie",MessageFormat(TEMPLATE,cookie.get...))
I managed the same resulting cookie definition as JSON, but without backslashes.
In case of having several cookies, addHeader("Set-Cookie") only creates/updates the desired cookie. The other ones are maintained and won't be altered.

public class StateDate{
#JsonRawValue
Boolean state;
#JsonRawValue
String date;
public String toJson() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonWriteFeature.QUOTE_FIELD_NAMES.mappedFeature(), false);
try {
return mapper.writeValueAsString(this);
} catch (com.fasterxml.jackson.core.JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}

I've faced similar issue, Following configuration will help sort the issue:
final ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, false);

For some people who still need an answer if struggling
Try adding #JsonRawValue to the field.
The #JsonRawValue annotation can instruct Jackson to serialize a property exactly as is.

Even I came across this problem today and I stumbled across this question. People have provided multiple ways of removing the backslashes, but the thing is that the problem goes down to the very essence of what we are trying to do here.
We want to return the json response of an api call, but we are returning it as a JSONString formatted in way so that it can be printed, read and understood in Java. When you print it it looks exactly the way you want it to be when you return it.
Long story short, you must return the bytes from the function, not a String. Change the return type to byte[] and return this:
new ObjectMapper().writeValueAsString(response).getBytes(StandardCharset.UTF_8);
This will give you the purest JSON you ever want to read. Mostly, people face this issue when on the other side they are reading from an InputStream and are unable to map it to the same class and it does not work. This is how you'll fix it.

It should not be a problem, just you need to parse it in javascript and use it : JSON.parse(response)

Related

How can I have different names for the same field in different APIs?—Jackson

I have an API whose response is as follows:
{
ruleId:”123”,
ruleName:”Rule1”
}
Now I am introducing a new Api which exactly has these fields but the response should not have name as ruleId ,ruleName but as id,name:
{
id:”123”,
name:”Rule1”
}
I should change in such a way so that the previous Api response should not be impacted.
Thought to use JsonProperty /JsonGetter but it will change the previous Api response as well.
Is there any way that I can have 2 getters for the same field and then use one getter for previous Apis and other one for my purpose? (My concern is only when converting Pojo to JSON)
Can anyone help?
Since you want serialize the object differently in different cases, using jackson mix-in is preferred.
Here is example how to do that.
If your pojo looks something like this:
public class CustomPojo {
private String ruleId;
private String ruleName;
public String getRuleId() {
return ruleId;
}
public void setRuleId(String ruleId) {
this.ruleId = ruleId;
}
public String getRuleName() {
return ruleName;
}
public void setRuleName(String ruleName) {
this.ruleName = ruleName;
}
}
First, you need to create one interface (or class) like this:
import com.fasterxml.jackson.annotation.JsonProperty;
public interface CostomPojoMixin {
#JsonProperty("Id")
String getRuleId();
#JsonProperty("name")
String getRuleName();
}
This interface will be used to rename fields ruleId and ruleName during serilization.
Then when you have all this setup you can write controller method and customize ObjectMapper:
#GetMapping(value = "/test/mixin")
public String testMixin() throwsJsonProcessingException {
CostomPojo cp = new CostomPojo();
cp.setRuleId("rule");
cp.setRuleName("name");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.addMixIn(CustomPojo.class, CostomPojoMixin.class);
String json = objectMapper.writeValueAsString(cp);
return json;
}
This endpoint should return response like this:
{"Id":"rule","name":"name"}

How to conditionally deserialize to a POJO field using Jackson?

How can I conditionally deserialize a JSON string to a POJO field?
I receive a JSON string like so:
{
"status": "we stuck",
"data" : "someData"
}
but "someData" can be just a string "under the bridge" or can be something like "['bridge 5', 'Mandela bridge']" or "[{'incident 1' : '['bridge 1', 'bridge 2]'},{'incident 2' : ['bridge 99', 'what ever else']}]"
I want to return the json string AS IS if "data" is an array then I will map to a different Type that deals with the array
I have a java class:
class Response {
String status;
String data;
}
the other Type will have data as
ArrayList<SomeOtherType> data;
This is what i have so far
ObjectMapper mapper = new ObjectMapper();
Response rspns = mapper.readValue(<theJSONStrHere>, Response.class);
this fails when data is an array, giving me the message
can not deserialize instance of java.lang.String out of START_ARRAY token
I don't know where to go from here.
You can either use a custom deserializer as aussie said or you can just modify your working solution.
class Response {
String status;
String data;
}
class Other {
String status;
ArrayList<SomeOtherType> data;
}
ObjectMapper mapper = new ObjectMapper();
Other rspns = mapper.readValue(<theJSONStrHere>, Other.class);
This will parse the JSON String to the Other class with the ArrayList.
Now it's your turn to implement the decision of then to use
Other rspns = mapper.readValue(<theJSONStrHere>, Other.class);
or when to use
Responserspns = mapper.readValue(<theJSONStrHere>, Response.class);
Note: The above is a quick and dirty solution. It works like that but I would highly recommend to use a custom deserializer, which handles the logic of what it is and what to return.
Also keep in mind that for this to work the best you might consider building the POJO structure to multiple classes which extend a base class and then work generic.
example:
class response {
String status;
}
class simpleResponse extends response {
String data;
}
class listResponse extends response {
ArrayList<Type> data;
}
class MyDeserializer extends JSONDeserializer<E extends response> {
public E deserialize...) {
}
}
To get an actual working example read about Jackson
Dont make it complicated think simple..
There are two ways
First taking List os string/(or any other type)
private List<String> tags;
Second taking List of class (if you need more than one parameters)
List<PageLink> pagelinks;
See below case example......
public class PagesJson {
private String ln;
private int pageno;
private List<String> tags;
private List<PageLink> pagelinks;
private String error;
}
public class PageLink {
private String title= null;
private String url;
}
Now json of PagesJson class as below
{"ln":en,"count":100,"viewcount":23,"pageno":17,"tags":["Ensuring safe motherhood","pregnancy health in women","Abortion"],"pagelinks":[{"title":"Abortion","url":"http://vikaspedia.in/health/women-health"},{"title":"Acts and Rules","url":"http://vikaspedia.in/social-welfare/scheduled-tribes-welfare/acts-and-rules"},{"title":"Acts and Rules ","url":"http://vikaspedia.in/social-welfare/unorganised-sector-1/acts-and-rules"}],"error":"Parameter Validation Error"}
{"ln":en,"count":100,"viewcount":23,"pageno":17,"tags":["Ensuring safe motherhood","pregnancy health in women","Abortion"],"pagelinks":[{"title":"Abortion","url":"http://vikaspedia.in/health/women-health"},{"title":"Acts and Rules","url":"http://vikaspedia.in/social-welfare/scheduled-tribes-welfare/acts-and-rules"},{"title":"Acts and Rules ","url":"http://vikaspedia.in/social-welfare/unorganised-sector-1/acts-and-rules"}],"error":"Parameter Validation Error"}
For Mapping json to class use jackson library as below.....
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
....
.....
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
PagesJson pj = mapper.readValue(response.toString(), PagesJson.class);
You can use Custom Deserializer on a Method OR a Class using below :
extends JsonDeserializer
then
#Override
public ReturnObject deserialize(JsonParser parser, DeserializationContext ctx)
throws IOException, JsonProcessingException {
JsonToken token = parser.getCurrentToken();
if(JsonToken.START_ARRAY.equals(token)){
//TODO your JSON Array code handling
}else{
//TO DO you JSON Object Handling
}
}

Spring Boot: Wrapping JSON response in dynamic parent objects

I have a REST API specification that talks with back-end microservices, which return the following values:
On "collections" responses (e.g. GET /users) :
{
users: [
{
... // single user object data
}
],
links: [
{
... // single HATEOAS link object
}
]
}
On "single object" responses (e.g. GET /users/{userUuid}) :
{
user: {
... // {userUuid} user object}
}
}
This approach was chosen so that single responses would be extensible (for example, maybe if GET /users/{userUuid} gets an additional query parameter down the line such at ?detailedView=true we would have additional request information).
Fundamentally, I think it is an OK approach for minimizing breaking changes between API updates. However, translating this model to code is proving very arduous.
Let's say that for single responses, I have the following API model object for a single user:
public class SingleUserResource {
private MicroserviceUserModel user;
public SingleUserResource(MicroserviceUserModel user) {
this.user = user;
}
public String getName() {
return user.getName();
}
// other getters for fields we wish to expose
}
The advantage of this method is that we can expose only the fields from the internally used models for which we have public getters, but not others. Then, for collections responses I would have the following wrapper class:
public class UsersResource extends ResourceSupport {
#JsonProperty("users")
public final List<SingleUserResource> users;
public UsersResource(List<MicroserviceUserModel> users) {
// add each user as a SingleUserResource
}
}
For single object responses, we would have the following:
public class UserResource {
#JsonProperty("user")
public final SingleUserResource user;
public UserResource(SingleUserResource user) {
this.user = user;
}
}
This yields JSON responses which are formatted as per the API specification at the top of this post. The upside of this approach is that we only expose those fields that we want to expose. The heavy downside is that I have a ton of wrapper classes flying around that perform no discernible logical task aside from being read by Jackson to yield a correctly formatted response.
My questions are the following:
How can I possibly generalize this approach? Ideally, I would like to have a single BaseSingularResponse class (and maybe a BaseCollectionsResponse extends ResourceSupport class) that all my models can extend, but seeing how Jackson seems to derive the JSON keys from the object definitions, I would have to user something like Javaassist to add fields to the base response classes at Runtime - a dirty hack that I would like to stay as far away from as humanly possible.
Is there an easier way to accomplish this? Unfortunately, I may have a variable number of top-level JSON objects in the response a year from now, so I cannot use something like Jackson's SerializationConfig.Feature.WRAP_ROOT_VALUE because that wraps everything into a single root-level object (as far as I am aware).
Is there perhaps something like #JsonProperty for class-level (as opposed to just method and field level)?
There are several possibilities.
You can use a java.util.Map:
List<UserResource> userResources = new ArrayList<>();
userResources.add(new UserResource("John"));
userResources.add(new UserResource("Jane"));
userResources.add(new UserResource("Martin"));
Map<String, List<UserResource>> usersMap = new HashMap<String, List<UserResource>>();
usersMap.put("users", userResources);
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(usersMap));
You can use ObjectWriter to wrap the response that you can use like below:
ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writer().withRootName(root);
result = writer.writeValueAsString(object);
Here is a proposition for generalizing this serialization.
A class to handle simple object:
public abstract class BaseSingularResponse {
private String root;
protected BaseSingularResponse(String rootName) {
this.root = rootName;
}
public String serialize() {
ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writer().withRootName(root);
String result = null;
try {
result = writer.writeValueAsString(this);
} catch (JsonProcessingException e) {
result = e.getMessage();
}
return result;
}
}
A class to handle collection:
public abstract class BaseCollectionsResponse<T extends Collection<?>> {
private String root;
private T collection;
protected BaseCollectionsResponse(String rootName, T aCollection) {
this.root = rootName;
this.collection = aCollection;
}
public T getCollection() {
return collection;
}
public String serialize() {
ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writer().withRootName(root);
String result = null;
try {
result = writer.writeValueAsString(collection);
} catch (JsonProcessingException e) {
result = e.getMessage();
}
return result;
}
}
And a sample application:
public class Main {
private static class UsersResource extends BaseCollectionsResponse<ArrayList<UserResource>> {
public UsersResource() {
super("users", new ArrayList<UserResource>());
}
}
private static class UserResource extends BaseSingularResponse {
private String name;
private String id = UUID.randomUUID().toString();
public UserResource(String userName) {
super("user");
this.name = userName;
}
public String getUserName() {
return this.name;
}
public String getUserId() {
return this.id;
}
}
public static void main(String[] args) throws JsonProcessingException {
UsersResource userCollection = new UsersResource();
UserResource user1 = new UserResource("John");
UserResource user2 = new UserResource("Jane");
UserResource user3 = new UserResource("Martin");
System.out.println(user1.serialize());
userCollection.getCollection().add(user1);
userCollection.getCollection().add(user2);
userCollection.getCollection().add(user3);
System.out.println(userCollection.serialize());
}
}
You can also use the Jackson annotation #JsonTypeInfo in a class level
#JsonTypeInfo(include=As.WRAPPER_OBJECT, use=JsonTypeInfo.Id.NAME)
Personally I don't mind the additional Dto classes, you only need to create them once, and there is little to no maintenance cost. And If you need to do MockMVC tests, you will most likely need the classes to deserialize your JSON responses to verify the results.
As you probably know the Spring framework handles the serialization/deserialization of objects in the HttpMessageConverter Layer, so that is the correct place to change how objects are serialized.
If you don't need to deserialize the responses, it is possible to create a generic wrapper, and a custom HttpMessageConverter (and place it before MappingJackson2HttpMessageConverter in the message converter list). Like this:
public class JSONWrapper {
public final String name;
public final Object object;
public JSONWrapper(String name, Object object) {
this.name = name;
this.object = object;
}
}
public class JSONWrapperHttpMessageConverter extends MappingJackson2HttpMessageConverter {
#Override
protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
// cast is safe because this is only called when supports return true.
JSONWrapper wrapper = (JSONWrapper) object;
Map<String, Object> map = new HashMap<>();
map.put(wrapper.name, wrapper.object);
super.writeInternal(map, type, outputMessage);
}
#Override
protected boolean supports(Class<?> clazz) {
return clazz.equals(JSONWrapper.class);
}
}
You then need to register the custom HttpMessageConverter in the spring configuration which extends WebMvcConfigurerAdapter by overriding configureMessageConverters(). Be aware that doing this disables the default auto detection of converters, so you will probably have to add the default yourself (check the Spring source code for WebMvcConfigurationSupport#addDefaultHttpMessageConverters() to see defaults. if you extend WebMvcConfigurationSupport instead WebMvcConfigurerAdapter you can call addDefaultHttpMessageConverters directly (Personally I prefere using WebMvcConfigurationSupport over WebMvcConfigurerAdapter if I need to customize anything, but there are some minor implications to doing this, which you can probably read about in other articles.
Jackson doesn't have a lot of support for dynamic/variable JSON structures, so any solution that accomplishes something like this is going to be pretty hacky as you mentioned. As far as I know and from what I've seen, the standard and most common method is using wrapper classes like you are currently. The wrapper classes do add up, but if you get creative with your inheretence you may be able to find some commonalities between classes and thus reduce the amount of wrapper classes. Otherwise you might be looking at writing a custom framework.
I guess you are looking for Custom Jackson Serializer. With simple code implementation same object can be serialized in different structures
some example:
https://stackoverflow.com/a/10835504/814304
http://www.davismol.net/2015/05/18/jackson-create-and-register-a-custom-json-serializer-with-stdserializer-and-simplemodule-classes/

JSON unmarshalling using JAX-RS and MOXy

I'm implementing RESTFul web service using Jersey 2.22.1 with MOXY as Json Provider.
For example I have the following entity User:
public class User {
private String id;
private String email;
private Address address;
private List<Phone> phones;
// getters & setters
}
and additional classes
public class Address {
private String type;
private String value;
// getters & setters
}
public class Phone {
private String type;
private String value;
// getters & setters
}
This is my JAX-RS resource implementation:
#POST
public Response create(User user) {
// some logic
}
Now when I'm sending POST request containting following json data:
{
"id":"qwe12",
"email":"emailname#g-mail.com",
"address":{
"type":"1WHEN-Honorable",
"value":"1WHEN-M"
},
"phones":[
{
"type":"HOME",
"number":"034-2342-12-31"
},
{
"type":"WORK",
"number":"31-21-3211-32"
}
]
}
it works perfectly, MOXY automatically maps this json to user object and it's fine
But I need to handle json with another level of nesting, like this:
{
"user":{
"id":"qwe12",
"email":"emailname#g-mail.com",
"address":{
"type":"1WHEN-Honorable",
"value":"1WHEN-M"
},
"phones":[
{
"type":"HOME",
"number":"034-2342-12-31"
},
{
"type":"WORK",
"number":"31-21-3211-32"
}
]
}
}
As you can see there is another key called user, and I know it's not a good json structure but it's a requirement and I have to accept it as it is. Now I need to be able to handle it. For now I can see only one solution.
I can add another one class wrapper aroung User and pass it to the create method.
So it would look this:
JAX-RS resource:
#POST
public Response create(UserWrapper user) {
// some logic
}
And java class:
public class UserWrapper {
private User user;
// getters & setters
}
It's working solution but I don't really like it because I need to add one more additional class. Would like to here your suggestions how to keep my java classes as it is and be able to accept json with one more level of nesting (i mean this user key).
Thanks in advance!
May not be the answer you're looking for, but I recommend using Jackson instead of MOXy. It's a more mature JSON framework with more features, and just works better. There may be a way with MOXy, but here is the Jackson way
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.1</version>
</dependency>
<!-- You need to remember to remove MOXy -->
In a ContextResolver, configure the ObjectMapper to unwrap the root value
#Provider
public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> {
final ObjectMapper mapper;
public MyObjectMapperProvider() {
mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
}
#Override
public ObjectMapper getContext(Class<?> type) {
return defaultObjectMapper;
}
}
private static ObjectMapper createDefaultMapper() {
return mapper;
}
}
The value it will look for to deserialize will either be
The value in a #JsonRootName annotation, e.g. #JsonRootName("user") (on the class)
The value in a #XmlRootElement annotation, e.g. #XmlRootElment(name="user") (on the class)
If there is no annotation, then the name of the class, with the first letter lower cased.
Also not, unless you are using any MOXy specific features, making the switch to Jackson, you probably will not need to make any changes at all to your classes. Jackson also supports JAXB annotations (for the most part).
If you want the response to be wrapped, you can also use
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);

Create simple JSON structure using jackson

I'd just like to create the Jackson mapping equivalent of the below :
{\"isDone\": true}
I think I need to create a class like this :
public class Status {
private boolean isDone;
public boolean isDone{
return this.isDone;
}
public void setDone(boolean isDone){
this.isDone = isDone;
}
}
But how do I instatiate it and then write the JSON to a string ?
A problem with your example and Jackson is the default choices of JSON property names: Jackson will see isDone and setDone and choose done as the JSON property name. You can override this default choice using the JsonProperty annotation:
public class Status
{
private boolean isDone;
#JsonProperty("isDone")
public boolean isDone()
{
return this.isDone;
}
#JsonProperty("isDone")
public void setDone(boolean isDone)
{
this.isDone = isDone;
}
}
Then:
Status instance = new Status();
String jsonString = null;
instance.setDone(true);
ObjectMapper mapper = new ObjectMapper();
jsonString = mapper.writeValueAsString(instance);
Now jsonString contains { "isDone" : true }. Note that you can also write the string to an OutputStream using ObjectMapper.writeValue(OutputStream, Object), or to a Writer using ObjectMapper.writeValue(Writer, Object).
In this case you really only need the JsonProperty annotation on either of your accessors, but not both. Just annotating isDone will get you the JSON property name that you want.
An alternative to using the JsonProperty annotation is to rename your accessors setIsDone/getIsDone. Then the annotations are unnecessary.
See the quick and dirty Jackson tutorial: Jackson in 5 minutes. Understanding of the specific properties came from looking through the docs for Jackson annotations.
Right. The code needed:
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(new Status()));

Categories