Using conditions to dynamically exclude POJO property in Jackson json serialization

前端 未结 3 1854
梦谈多话
梦谈多话 2020-12-11 10:21

I have a requirement to dynamically exclude certain property within a List of a defined POJO. The main POJO to be serialized is:

public class Foo
{
    List&         


        
相关标签:
3条回答
  • 2020-12-11 10:36

    You should write a custom Jackson filter which would filter out a POJO property depending on other property value. You should override the PropertyFilter.serializeAsField() method to get access to the instance of the serialized object. Here is an example:

    public class JacksonFilter2 {
        @JsonFilter("filter")
        public static class Bar {
            public final int id;
            @JsonIgnore
            public final boolean ignoreId;
            public final String name;
    
            public Bar(int id, boolean ignoreId, String name) {
                this.id = id;
                this.ignoreId = ignoreId;
                this.name = name;
            }
        }
    
        public static class ExcludeIdFilter extends SimpleBeanPropertyFilter {
    
            @Override
            protected boolean include(BeanPropertyWriter writer) {
                return true;
            }
    
            @Override
            protected boolean include(PropertyWriter writer) {
                return true;
            }
    
            @Override
            public void serializeAsField(Object pojo,
                                         JsonGenerator jgen,
                                         SerializerProvider provider,
                                         PropertyWriter writer) throws Exception {
                if (pojo instanceof Bar
                        && "id".equals(writer.getName())
                        && ((Bar) pojo).ignoreId) {
                   writer.serializeAsOmittedField(pojo, jgen, provider);
                } else {
                    super.serializeAsField(pojo, jgen, provider, writer);
                }
            }
        }
    
        public static void main(String[] args) throws JsonProcessingException {
            List<Bar> bars = Arrays.asList(new Bar(1, false, "one"),  new Bar(2, true, "two"));
            ObjectMapper mapper = new ObjectMapper();
            mapper.setFilters(new SimpleFilterProvider().addFilter("filter", new ExcludeIdFilter()));
            System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(bars));
        }
    
    }
    

    Output:

    [ {
      "id" : 1,
      "name" : "one"
    }, {
      "name" : "two"
    } ]
    
    0 讨论(0)
  • 2020-12-11 10:47

    I just saw the culprit. Thanks a lot @Alexey for staying with me on this. After much try, I discover Jackson 2.4.2 might have required that I place my serialzer within the model it would work with. I wonder why though, but probably due to Java object serialization requirements, Jackson was failing to map the Filter at runtime. I hope Tatu would note this in Jackson documentation

    public class PostProject
    {
        /* The field template of this project */
        private List< FieldTemplateObject > field_templates;
    
        /**
         * @author Damilola Okuboyejo
         */
        @JsonFilter( "FieldTemplateIdFilter" )
        public static class FieldTemplateObject
        {
          private int     id;
          private boolean is_inherited;
          private String  item_type;
    
          /**
           * @return the id
           */
          public int getId()
          {
             return id;
          }
    
          /**
           * @param id
           *           the id to set
           */
          public void setId( int id )
          {
             this.id = id;
          }
    
          /**
           * @return the is_inherited
           */
          public boolean isIs_inherited()
          {
             return is_inherited;
          }
    
          /**
           * @param is_inherited
           *           the is_inherited to set
           */
          public void setIs_inherited( boolean is_inherited )
          {
             this.is_inherited = is_inherited;
          }
    
          /**
           * @return the item_type
           */
          public String getItem_type()
          {          
             return item_type;
          }
    
          /**
           * @param item_type
           *           the item_type to set
           */
          public void setItem_type( String item_type )
          {
             this.item_type = item_type;
          }
       }
    
       public static class ModelFieldSerializer extends SimpleBeanPropertyFilter
       {
          @Override
          protected boolean include( BeanPropertyWriter writer )
          {
             return true;
          }
    
          @Override
          protected boolean include( PropertyWriter writer )
          {
             return true;
          }
    
          @Override
          public void serializeAsField( Object pPojo, JsonGenerator pJgen,
                SerializerProvider pProvider, PropertyWriter pWriter )
                throws Exception
          {
             if( pPojo instanceof FieldTemplateObject )
             {
                 boolean vAllowId = ((FieldTemplateObject) pPojo).isIs_inherited();
                 if( !vAllowId && ("id".equals( pWriter.getName() )) )
                 {
                   return; // skip the id property
                 }
                 else
                 {
                   super.serializeAsField( pPojo, pJgen, pProvider, pWriter );
                 }
             }
          }
        }
    }
    
    0 讨论(0)
  • 2020-12-11 10:53

    I am using Jackson 2.4.2.

    Model object is:

    public class PostProject
    {
        /* The field template of this project */
        private List< FieldTemplateObject > field_templates;
    
        /**
         * @author Damilola Okuboyejo
         */
        @JsonFilter( "FieldTemplateIdFilter" )
        public static class FieldTemplateObject
        {
          private int     id;
          private boolean is_inherited;
          private String  item_type;
    
          /**
           * @return the id
           */
          public int getId()
          {
             return id;
          }
    
          /**
           * @param id
           *           the id to set
           */
          public void setId( int id )
          {
             this.id = id;
          }
    
          /**
           * @return the is_inherited
           */
          public boolean isIs_inherited()
          {
             return is_inherited;
          }
    
          /**
           * @param is_inherited
           *           the is_inherited to set
           */
          public void setIs_inherited( boolean is_inherited )
          {
             this.is_inherited = is_inherited;
          }
    
          /**
           * @return the item_type
           */
          public String getItem_type()
          {
             if( item_type == null )
             {
                item_type = PostProject.item_type;
             }
             return item_type;
          }
    
          /**
           * @param item_type
           *           the item_type to set
           */
          public void setItem_type( String item_type )
          {
             this.item_type = item_type;
          }
       }
    }
    

    Myy serializer is like so:

    public static class ModelFieldSerializer extends SimpleBeanPropertyFilter
    {
      @Override
      protected boolean include( BeanPropertyWriter writer )
      {
         return true;
      }
    
      @Override
      protected boolean include( PropertyWriter writer )
      {
         return true;
      }
    
      @Override
      public void serializeAsField( Object pPojo, JsonGenerator pJgen,
            SerializerProvider pProvider, PropertyWriter pWriter )
            throws Exception
      {
         if( pPojo instanceof FieldTemplateObject )
         {
            if( ("id".equals( pWriter.getName() ))
                  && ((FieldTemplateObject) pPojo).isIs_inherited() )
            {
               pWriter.serializeAsOmittedField( pPojo, pJgen, pProvider );
            }
            else
            {
               super.serializeAsField( pPojo, pJgen, pProvider, pWriter );
            }
         }
      }
    }
    

    NOTE: The model class is passed through the network in a client-server architecture env

    0 讨论(0)
提交回复
热议问题