Overrride global jackson config - java

Im my app null values will not be serialized to json, and its ok. But in one specific case, I'd like to have null values send to client. How could I achieve that ?
class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
for this class I tried with JsonInclude.Always but its defualt value that gets overriden in config later on.

Use JsonInclude annotation. Example:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);
System.out.println(mapper.writeValueAsString(new User()));
}
}
#JsonInclude
class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Above code prints:
{"name":null}
Default value in JsonInclude is ALWAYS:
/**
* Inclusion rule to use for instances (values) of types (Classes) or
* properties annotated.
*/
public Include value() default Include.ALWAYS;
Other option is to use JsonSerialize annotation:
#JsonSerialize(include = Inclusion.ALWAYS)
class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Result is the same as for JsonInclude.

Try
#JsonInclude(JsonInclude.Include.ALWAYS)

Related

How to deserialize JSON with #JsonCreator and #JsonGetter

I have the JSON looks like the following:
{
"name":"John",
"n_age":500
}
and I have a class Person:
public class Person {
private final String name;
private final int age;
#JsonCreator
public Person(#JsonProperty("name") String name) {
this.name = name;
this.age = 100;
}
public String getName() {
return name;
}
#JsonGetter("n_age")
public int getAge() {
return age;
}
}
I need to deserialize and serialize it, but when I'm trying to deserialize this JSON I get unexpected result.
public static void main(String... args) {
ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue(args[0], Person.class);
System.out.println(person.getAge()); // I got 500, but I expect 100.
}
Why when I'm trying to deserialize it the #JsonGetter annotation is used for it?
How can I disable #JsonGetter annotation when I try to deserialize the JSON?
If #JsonGetter is used as is currently, it will map property n_age to field age. To citate the docs - It can be used as an alternative to more general JsonProperty annotation (which is the recommended choice in general case).
To fix this behaviour, you need to:
Tell jackson to ignore property n_age, otherwise you will get exception for unrecognized property not marked as ignorable - #JsonIgnoreProperties("n_age").
Tell jackson to allow getters for ignored properties(basically make it readonly) - #JsonIgnoreProperties(value = {"n_age"}, allowGetters = true)
In the end, Person should look like this:
#JsonIgnoreProperties(value = {"n_age"}, allowGetters = true)
public class Person {
private final String name;
private final int age;
#JsonCreator
public Person(#JsonProperty("name") String name) {
this.name = name;
this.age = 100;
}
public String getName() {
return name;
}
#JsonGetter("n_age")
public int getAge() {
return age;
}
#Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
I found the solution for fixing my issue, maybe it's a bad way, but it works for me as well. I'm ignoring the n_age property during deserialization and allowing getters during serialization.
Thanks a lot #Chaosfire for the help!
#JsonIgnoreProperties({"n_age"}, allowGetters = true)
public class Person {
private final String name;
private final int age;
#JsonCreator
public Person(#JsonProperty("name") String name) {
this.name = name;
this.age = 100;
}
public String getName() {
return name;
}
#JsonGetter("n_age")
public int getAge() {
return age;
}
}

Java beans binding in GUI

I created a User bean class and bind it to a JTextField. I'd like to update the textfield when a method setName of the bean is call. Here is the code:
package newpackage;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public class User {
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
propertyChangeSupport.firePropertyChange(null, null, null);
}
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
}
I use NetBeans to design a GUI. It works. But I was wondering whether it is a correct way to implement bean binding with a Swing component.
Almost. Try something like this (untested):
public void setName(String name) {
String oldName = this.name;
this.name = name;
propertyChangeSupport.firePropertyChange("name", oldName, name);
}
See the Javadoc.

Java Json Jackson saving private fields without getters and setters

I am using Jackson to save my java object (Person.class) as a json file and load from it using jackson as well.
This is what I am saving at the moment:
public class Person {
private String name;
private int yearOfBirth;
public Person(String name, int yearOfBirth) {
this.name = name;
this.yearOfBirth = yearOfBirth;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getYearOfBirth() {
return yearOfBirth
}
public void setYearOfBirth(int yearOfBirth) {
this.yearOfBirth = yearOfBirth;
}
}
Even though a person's name (in this case) CANNOT be changed, nor can their year of birth, I have to have the getters and setters for Jackson to recognise the values otherwise it will give an exception:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "name"
How can i make my fields name and yearOfBirth (without making them PUBLIC ofcourse) final fields uneditable after initialisation.
This is my saving and loading using jackson:
saving:
public void savePerson(File f, Person cache) {
ObjectMapper saveMapper = new ObjectMapper()
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
saveMapper.setVisibilityChecker(
saveMapper.getSerializationConfig().
getDefaultVisibilityChecker().
withFieldVisibility(JsonAutoDetect.Visibility.ANY).
withGetterVisibility(JsonAutoDetect.Visibility.NONE).
withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)
);
ObjectWriter writer = saveMapper.writer().withDefaultPrettyPrinter();
writer.writeValue(f, cache);
}
loading:
public Person load(File f) {
return new ObjectMapper().readValue(f, Person.class);
}
User #JsonProperty and it will work.
import com.fasterxml.jackson.annotation.JsonProperty;
public class Person {
private final String name;
private final int yearOfBirth;
public Person(#JsonProperty("name") String name, #JsonProperty("yearOfBirth") int yearOfBirth) {
this.name = name;
this.yearOfBirth = yearOfBirth;
}
public String getName() {
return name;
}
public int getYearOfBirth() {
return yearOfBirth;
}
}

Java casting enum to a class

I have a class which is identical to enum. The only difference is that I create the class so that I can dynamically create the enums. What I want is to override the cast operation of enum so that I can give the enum instance to a method where it gets the class instance.
Example:
public enum SpecialEnum {
FIRST("First"), SECOND("Second");
private String name;
SpecialEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class SpecialClass {
private String name;
public SpecialClass(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public void displayName(SpecialClass specialClass) {
System.out.println(specialClass.getName());
}
Lets say that the SpecialClass instances are coming from a server where I display them. But I also want to use my pre-defined Special enum classes as well. I know that I could create static instances of SpecialClass and use them but not that it looks messy, also using enums are beneficial to my occasion as well. Is there a way to override casting operation of the enum class of a work around maybe?
Extract an interface:
public interface Named {
public String getName();
}
public class SpecialClass implements Named {
private String name;
public SpecialClass(String name) {
this.name = name;
}
#Override
public String getName() {
return name;
}
}
public enum SpecialEnum implements Named {
FIRST("First"), SECOND("Second");
private String name;
SpecialEnum(String name) {
this.name = name;
}
#Override
public String getName() {
return name;
}
}
public void displayName(Named specialClass) {
System.out.println(specialClass.getName());
}

How to use Jackson ObjectMapper to convert to Pojo for multiple data

I would like to convert the following string/ JSONObject to POJO,
{"list":["\r\n{\r\n\"id\":\"1\",\r\n\"protocol\":\"udp\",\r\n\"srcPorts= \":\"3000-4000 \",\r\n\"destPorts\":\"1790-2000\"\r\n}","\r\n{\r\n\"id\":\"2\",\r\n \"protocol\":\"tcp\",\r\n\"srcPorts\":\"3000-4000\",\r\n\"destPorts\":\"1790-2000 \"\r\n}"],"user":"\r\n{\r\n\"name\":\"John\",\r\n\"address\":\"x.x.x.x\",\r\n\"email \":\"john#p.com\"\r\n}"}
How do I convert to Pojo using Jackson ObjectMapper.
The 2 Pojo classes are as follows.
The user part in the string above should map to the java file - User.java
public class User
{
private String name;
private String address;
private String email;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAddress()
{
return address;
}
public void setaddress(String Address)
{
this.address = address;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
}
The List part in the string above should map to the java file - TestCase.java
public class TestCase
{
private String id;
private String protocol;
private String srcPorts;
private String destPorts;
public String getProtocol()
{
return protocol;
}
public void setProtocol(String protocol)
{
this.protocol = protocol;
}
public String getSrcPorts()
{
return srcPorts;
}
public void setSrcPorts(String srcPorts)
{
this.srcPorts = srcPorts;
}
public String getDestPorts()
{
return destPorts;
}
public void setDestPorts(String destPorts)
{
this.destPorts = destPorts;
}
public String getID()
{
return id;
}
public void setID(String id)
{
this.id = id;
}
}
Following code should help.
class ParseJson{
private User user;
private TestCase testCase;
//getter and setter methods
}
//and then call objectMapper -
String jsonString = "";//Json input
ObjectMapper mapper = new ObjectMapper();
ParseJson parsedJson = mapper.readValue(jsonString, ParseJson.class);
User user = parsedJson.getUser();
TestCase testCase = parsedJson.getTestCase();
Since your JSON object does not contain any type information, the best approach would be to use a custom deserializer class for Jackson, at least for the outer class. Alternatively, you can try annotating your POJO classes with Jackson annotations, and hope that the Right Thing happens.
In any case, you will have to make Jackson aware of your context by calling one of the ObjectMapper.readValue() methods with the proper class type argument, so that Jackson will know what it is that is being deserialized.

Categories