/** * Here we will modify serializer such that it has two modes: default handling when no JsonView * is enabled; and other (custom) when viess are enabled. Note that we could also just have * forced serialization for all cases. */ @Override protected void processViews(SerializationConfig config, BeanSerializerBuilder builder) { // Let's use default serializer modification as the baseline super.processViews(config, builder); /* And only change handling of that one bean (more likely, * you would want to handle all classes in a package, or with * some name -- this would be less work than having separate * custom serializer for all classes) */ BasicBeanDescription beanDesc = builder.getBeanDescription(); if (beanDesc.getBeanClass() == Bean.class) { List<BeanPropertyWriter> props = builder.getProperties(); BeanPropertyWriter[] writers = props.toArray(new BeanPropertyWriter[props.size()]); for (int i = 0; i < writers.length; ++i) { String pname = writers[i].getName(); if ("secret".equals(pname)) { // remove serializer, filters it out writers[i] = null; } else if ("name".equals(pname)) { // This one we'll just upper case for fun writers[i] = new UpperCasingWriter(writers[i]); } } // Important: update builder with filtered property definitions builder.setFilteredProperties(writers); } }
public void testJackson428() throws Exception { ObjectMapper serMapper = new ObjectMapper(); TypeResolverBuilder<?> serializerTyper = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL); serializerTyper = serializerTyper.init(JsonTypeInfo.Id.NAME, createTypeNameIdResolver(true)); serializerTyper = serializerTyper.inclusion(JsonTypeInfo.As.PROPERTY); serMapper.setDefaultTyping(serializerTyper); // Let's start by constructing something to serialize first MapHolder holder = new MapHolder(); holder.map = new HashMap<MapKey, List<Object>>(); List<Object> ints = new ArrayList<Object>(); ints.add(Integer.valueOf(3)); holder.map.put(new MapKey("key"), ints); String json = serMapper.writeValueAsString(holder); // Then deserialize: need separate mapper to initialize type id resolver appropriately ObjectMapper deserMapper = new ObjectMapper(); TypeResolverBuilder<?> deserializerTyper = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL); deserializerTyper = deserializerTyper.init(JsonTypeInfo.Id.NAME, createTypeNameIdResolver(false)); deserializerTyper = deserializerTyper.inclusion(JsonTypeInfo.As.PROPERTY); deserMapper.setDefaultTyping(deserializerTyper); MapHolder result = deserMapper.readValue(json, MapHolder.class); assertNotNull(result); Map<?, ?> map = result.map; assertEquals(1, map.size()); Map.Entry<?, ?> entry = map.entrySet().iterator().next(); Object key = entry.getKey(); assertEquals(MapKey.class, key.getClass()); Object value = entry.getValue(); assertTrue(value instanceof List<?>); List<?> list = (List<?>) value; assertEquals(1, list.size()); assertEquals(Integer.class, list.get(0).getClass()); assertEquals(Integer.valueOf(3), list.get(0)); }