0

Question How to indicate ObjectMapperthat he should filter object's nested collection by some criteria (field). See explanation via code:

Explanation via code:

I have to convert Container object to JSON. But I want to filter entries collection based on Entry.value field. I mean I want to serialize Container and include only that Entries which value == 1.

public class Container {  
  List<Entry> entries;

  public void setEntries(List<Entry> entries) {
    this.entries = entries;
  }
}

public class Entry {
  int value;

  public Entry(int value) {
    this.value = value;
  }
}


public static void main(String[] args) {
  ObjectMapper mapper = new ObjectMapper();
  Container container = new Container();
  container.setEntries(new LinkedList<Entry>({
    {
      add(new Entry(1));
      add(new Entry(2));
      add(new Entry(1));
    }
  }))
  // Now I want to get container object only with two elements in list
  mapper.writeValueAsString(container);
}
VB_
  • 45,112
  • 42
  • 145
  • 293

1 Answers1

2

You can make Entry implement JsonSerializable. In Jackson 2.x it will give:

public class Entry
    implements JsonSerializable
{
    int value;

    public Entry(int value) 
    {
        this.value = value;
    }

    @Override
    public void serialize(final JsonGenerator jgen,
        final SerializerProvider provider)
        throws IOException
    {
        // Don't do anything if value is not 1...
        if (value != 1)
            return;

        jgen.writeStartObject();
        jgen.writeNumberField("value", 1);
        jgen.writeEndObject();
    }

    @Override
    public void serializeWithType(final JsonGenerator jgen,
        final SerializerProvider provider, final TypeSerializer typeSer)
        throws IOException
    {
        serialize(jgen, provider);
    }
}

Another solution would be to implement a custom JsonSerializer<Entry> and register it before you serialize; it would basically do the same as the above.

fge
  • 119,121
  • 33
  • 254
  • 329
  • I like the first approach. I'll test it in 20 minutes – VB_ Feb 25 '14 at 12:50
  • Note however that this is rather "definitive". If you intend to change that one day, going the custom serializer route will prove more suitable in the long run. – fge Feb 25 '14 at 12:51
  • thanks! it works for me. can you briefly count main advantages of `JsonSerializer` over `JsonSerializable`. For now, I see only disadvantages: I'll be forced to use separate mapper for each class. – VB_ Feb 25 '14 at 13:16
  • 1
    The advantage is that you can deserialize in more than one way should you need to do so one day; as to the disadvantage, I don't see what you mean? If you don't specify a serializer for a type, default serialization will be used... – fge Feb 25 '14 at 13:19
  • with `JsonSerializable` I will send to client only part of `comments`. So when client update profile, I have to deserialize it in such way, that I have all comments. As I understand it's what `JsonSerializer` is destined for. But is it possible without `JsonDesirializer`? – VB_ Feb 25 '14 at 13:24
  • Hold on. Deserialization is another matter entirely. Serialization will produce JSON from a POJO, deserialization will produce a POJO from JSON. So, which is it? – fge Feb 25 '14 at 13:28
  • the question is: how can I set hidden comments to profile at deserialization moment? – VB_ Feb 25 '14 at 13:40
  • And why not filter out comments from the list (by creating a new list with only the appropriate comments, for instance) _before_ you serialize? Wouldn't that be simpler? – fge Feb 25 '14 at 13:43
  • because I have a complex objects graph, which means that one profile has references to another profiles, it turn they have references to another and so on. – VB_ Feb 25 '14 at 13:50