2

As mentioned here, I know that I can convert Java objects to JSON (with Jackson)

ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(objectToBeConverted);

I know that I can exclude fields from being included in the JSON string using the @JsonIgnore annotation, but what if I want to convert the same class to JSON multiple times, but each time choosing different fields to ignore?

For example, if I have a class

class Foo {
    int a;
    int b;
    ...
}

can I do something like

Foo foo = new Foo();
String json1 = ow.writeValueAsString(foo).excludeField('b');
String json2 = ow.writeValueAsString(foo).excludeField('a');

so that the resulting strings look like

// json1
{
    a: 1234
}
// json2
{
    b: 5678
}

If Jackson can't do it, maybe Gson can? Or another library?

Da Mike
  • 447
  • 4
  • 17

3 Answers3

1

You can try using different mix-in interfaces. I found two ways to do this.

  1. Use methods for reading properties. You can then create a mix-in class that only defines the properties to exclude:

    public interface ExludeA {
        @JsonIgnore
        int getA();
    }
    
  2. Use @JsonIncludeProperties to not tell which properties to exclude, but which properties to include:

    @JsonIncludeProperties({ "b", "c" })
    public interface ExludeA {
    }
    

In both cases, add that mix-in to the object mapper:

objectMapper.addMixIn(Foo.class, ExcludeA.class);

There is one very, very important thing though - you must use a new ObjectMapper for each mix-in. If you use an ObjectMapper instance to serialize a Foo instance without mix-ins, then adding the mix-in won't help. That's probably because ObjectMapper instances cache some stuff.

Rob Spoor
  • 6,186
  • 1
  • 19
  • 20
1

Here is a simple approach if you could box up all primitive type in Foo.

For example: int -> Integer, boolean -> Boolean

@JsonInclude(Include.NON_NULL)
class Foo {
    Integer a;
    Integer b;
    ...
}

Then, just make a copy of Foo and set the property which you want to ignore to null.

Foo foo = new Foo();
foo.setA(1234);
foo.setB(5678);

Foo foo1 = objectMapper.readValue(objectMapper.writeValueAsString(foo), Foo.class);  // make a copy of Foo
foo1.setB(null);  // force to ignore B
String json1 = ow.writeValueAsString(foo1); // it will be {a:1234}
Kai-Sheng Yang
  • 1,535
  • 4
  • 15
  • 21
0

There is multiple solution based on your need:

First:
You can just define two different DTO for your purpose and every time you need to each one just use it.


Second:
You can use @JsonInclude(JsonInclude.Include.NON_NULL) annotation for the properties:

class Foo {

    @JsonInclude(JsonInclude.Include.NON_NULL)
    int a;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    int b;
}

P.S: You can use this annotation on class level as:

@JsonInclude(JsonInclude.Include.NON_NULL) 
class Foo {
    int a;
    int b;
}

Third:
Use can define a filter to ignore properties based on different conditions.

Define a simple class for your filter:

public class YourConditionalFilter {

    @Override
    public boolean equals(int a) {
        return a == 1234;
    }
}

And then add this filter as annotation on top of the property:

@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = YourConditionalFilter.class)
int a;
Mehdi Rahimi
  • 1,453
  • 5
  • 20
  • 31
  • What does the `return a == 1;` accomplish? – Da Mike Apr 27 '22 at 15:59
  • It's based on your condition, return true if you want to ignore or vice versa @DaMike – Mehdi Rahimi Apr 27 '22 at 16:02
  • 1
    But I won't know `a`'s value before hand. I don't care what its value is actually. I just want to ignore it from json whatever its value. – Da Mike Apr 27 '22 at 16:03
  • You can use Two different DTO's for your need or define a filter like this in confitional situation. I think there is no other choice and you can't ignore properties as you said with an *excludeField* method @DaMike – Mehdi Rahimi Apr 27 '22 at 16:05
  • Do you have tries `@JsonInclude(JsonInclude.Include.NON_NULL)` annotation on top of your properties `a` and `b`?This annotation just ignore null values and result will look like what you want. @Da Mike – Mehdi Rahimi Apr 27 '22 at 16:13