Spring Boot with #JsonIgnore [duplicate] - java

This question already has an answer here:
Return some object in my Json
(1 answer)
Closed 6 years ago.
If I need to ignore the serialization/deserialization from one field I put the #JsonIgnore on that field:
#JsonIgnore
private String name;
But if I only need in serialization or only in deserealization I put in getter or setter method.
but it`s possible to use in some method? If my user call:
http://myApp/public/user/1
I need to ignore the properties pass for example, but if my user call:
http://myApp/private/user/1
I don't need to ignore the properties pass
Is it possible?

You can achieve this by using Json Filter with a FilterProvider
you use #JsonFilter annotation to assign a filter name to your POJO.
before serialization, you attach an instance of SimpleBeanPropertyFilter to the filter name. the class has two factory methods for filters that work based on propertry names.
Here is an example of the annotation declaration:
#JsonFilter("filterByName")
public class So {
public String alwaysWrite = "alwaysWriteValue";
public String somtimeIgnore = "somtimeIgnoreValue";
}
here is a method that assignes a filter that will ignore somtimeIgnore property
public void dontWriteSomtimes(So so) {
ObjectMapper mapper = new ObjectMapper();
FilterProvider filters = new SimpleFilterProvider()
.addFilter("filterByName", SimpleBeanPropertyFilter.serializeAllExcept("somtimeIgnore"));
ObjectWriter writer = mapper.writer(filters);
try {
System.out.println(writer.writeValueAsString(so));
} catch (Exception e) {
e.printStackTrace();
}
}
output:
{"alwaysWrite":"alwaysWriteValue"}
here is a method that will write everything: just assign a non-existent or empty property:
public void writeEveryting(So so) {
ObjectMapper mapper = new ObjectMapper();
FilterProvider filters = new SimpleFilterProvider()
.addFilter("filterByName", SimpleBeanPropertyFilter.serializeAllExcept(""));
ObjectWriter writer = mapper.writer(filters);
try {
System.out.println(writer.writeValueAsString(so));
} catch (Exception e) {
e.printStackTrace();
}
}
output:
{"alwaysWrite":"alwaysWriteValue","somtimeIgnore":"somtimeIgnoreValue"}

Related

Custom Jackson serializer on specific fields

I'm looking to have multiple jackson deserializers for the same object(s) all based on a custom annotation.
Ideally I'd have a single POJO like:
public class UserInfo {
#Redacted
String ssn;
String name;
}
Under "normal" conditions I want this object to be serialized the default way:
{"ssn":"123-45-6789", "name":"Bob Smith"}
but for logging purposes (for example) I want to redact the SSN so it doesn't get saved in our logs:
{"ssn":"xxx-xx-xxxx", "name":"Bob Smith"}
I've also looked into using #JsonSerialize and come up with:
public class UserInfo {
#JsonSerialize(using = RedactedSerializer.class, as=String.class)
String firstName;
String lastName;
}
The problem with this is that it ALWAYS uses this rule. Can multiple #JsonSerializers be added and only the specified one be used within the runtime code?
I've also seen "views" but ideally I'd like to atleast show that the field was present on the request - even if I dont know the value.
The 100% safe way would be to use different DTO in different requests. But yeah, if you cant do that, use #JsonView and custom serializer, something like:
class Views {
public static class ShowSSN {}
}
private static class MyBean{
#JsonSerialize(using = MyBeanSerializer.class)
#JsonView(Views.ShowSSN.class)
String ssn;
//getter setter constructor
}
private class MyBeanSerializer extends JsonSerializer<String> {
#Override
public void serialize(String value, JsonGenerator gen,
SerializerProvider serializers) throws IOException {
Class<?> jsonView = serializers.getActiveView();
if (jsonView == Views.ShowSSN.class)
gen.writeString(value); // your custom serialization code here
else
gen.writeString("xxx-xx-xxxx");
}
}
And use it like:
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
MyBean bean = new MyBean("123-45-6789");
System.out.println(mapper.writerWithView(Views.ShowSSN.class)
.writeValueAsString(bean));
// results in {"ssn":"123-45-6789"}
System.out.println(mapper.writeValueAsString(bean));
// results in {"ssn":"xxx-xx-xxxx"}
}
Also for example in spring it would be really easy to use
#Controller
public class MyController {
#GetMapping("/withView") // results in {"ssn":"123-45-6789"}
#JsonView(Views.ShowSSN.class)
public #ResponseBody MyBean withJsonView() {
return new MyBean("123-45-6789");
}
#GetMapping("/withoutView") // results in {"ssn":"xxx-xx-xxxx"}
public #ResponseBody MyBean withoutJsonView() {
return new MyBean("123-45-6789");
}
}
I think you could achieve that dynamically by coding not annotations,
inside your methods, you can set the proper Serializer and switch between them
(The code depends on your Jackson version)
ObjectMapper mapper = new ObjectMapper();
SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null));
testModule.addSerializer(new RedactedSerializer()); // assuming serializer declares correct class to bind to
mapper.registerModule(testModule);
https://github.com/FasterXML/jackson-docs/wiki/JacksonHowToCustomSerializers

Jackson adds backslash in json

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)

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/

How to implement Jackson custom serialization outside a domain bean?

I have a Spring managed bean...
#Component("Foobean")
#Scope("prototype")
public class foobean {
private String bar1;
private String bar2;
public String getBar1() {
return bar1;
}
public void setBar1(String bar1) {
this.bar1 = bar1;
}
public String getBar2() {
return bar2;
}
public void setBar2(String bar2) {
this.bar2 = bar2;
}
}
...and because I am using Dojo Dgrid to display an ArrayList of this bean, I am returning it into the controller as a JSON string:
#Controller
#RequestMapping("/bo")
public class FooController {
#Autowired
private FooService fooService
#RequestMapping("action=getListOfFoos*")
#ResponseBody
public String clickDisplayFoos(
Map<String, Object> model) {
List<Foobean> foobeans = fooService.getFoobeans();
ObjectMapper objMapper = new ObjectMapper();
String FooJson = null;
try {
FooJson = objMapper.writeValueAsString(foobeans);
} catch (JsonGenerationException e) {
etc.
}
However, my grid needs an additional column which will contain a valid action for each Foo; that action is not really dependent on any data in individual Foos -- they'll all have the same valid action -- repeated on each line of the resulting DGrid -- but that value is actually dependent upon security roles on the session...which can't be sent to the front end in a Json. So, my solution is twofold:
First I need to add a "virtual" Json property to the bean... which I can do in the bean with #JsonProperty on a method...
#JsonProperty("validActions")
public String writeValidActions {
return "placeHolderForSerializerToChange";
}
...but it just generates a placeholder. To really generate a valid value,
I need to reference the security role of the session,
which I am very reluctant to code in the above method. (A service call in
the domain bean itself? Seems very wrong.) I
think I should create a custom serializer and put the logic -- and the reference
to the Session.Security role in there. Are my instincts right, not to
inject session info into a domain bean method? And if so, what would such a
custom serializer look like?
Yes, I wouldn't put Session Info in to the domain or access session directly in my domain.
Unless there is a specific reason, you could simply add the logic in your action class.
public String clickDisplayFoos(){
List<Foo> foos = service.getFoos();
for(iterate through foos){
foo.setValidAction(session.hasSecurityRole())
}
String json = objMapper.writeValueAsString(foobeans);
return json;
}
I don't like the idea of setting new values as part of the serialization process. I feel custom serializers are meant to transform the representation of a particular property rather than add new values to a property.

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