1
2
3
4
5
6
7
8
9
10
11
12
13
14 package com.addthis.codec.jackson;
15
16 import java.util.Iterator;
17
18 import com.fasterxml.jackson.databind.BeanDescription;
19 import com.fasterxml.jackson.databind.DeserializationConfig;
20 import com.fasterxml.jackson.databind.JavaType;
21 import com.fasterxml.jackson.databind.JsonDeserializer;
22 import com.fasterxml.jackson.databind.JsonNode;
23 import com.fasterxml.jackson.databind.deser.BeanDeserializerBase;
24 import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
25 import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
26 import com.fasterxml.jackson.databind.deser.std.DelegatingDeserializer;
27 import com.fasterxml.jackson.databind.deser.std.EnumDeserializer;
28 import com.fasterxml.jackson.databind.node.ObjectNode;
29 import com.typesafe.config.Config;
30 import com.typesafe.config.ConfigValue;
31
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 public class CodecBeanDeserializerModifier extends BeanDeserializerModifier {
36 private static final Logger log = LoggerFactory.getLogger(CodecBeanDeserializerModifier.class);
37
38 private final Config globalDefaults;
39 private final boolean modifyEnum;
40
41 public CodecBeanDeserializerModifier(Config globalDefaults) {
42 this.globalDefaults = globalDefaults;
43 this.modifyEnum = globalDefaults.getBoolean("addthis.codec.jackson.ignore.enum-case");
44 }
45
46 @Override public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
47 BeanDescription beanDesc,
48 JsonDeserializer<?> deserializer) {
49 if (deserializer instanceof DelegatingDeserializer) {
50 JsonDeserializer<?> delegatee = ((DelegatingDeserializer) deserializer).getDelegatee();
51 JsonDeserializer<?> replacementDelegatee = modifyDeserializer(config, beanDesc, delegatee);
52 return deserializer.replaceDelegatee(replacementDelegatee);
53 } else if (deserializer instanceof BeanDeserializerBase) {
54 BeanDeserializerBase beanDeserializer = (BeanDeserializerBase) deserializer;
55 ObjectNode fieldDefaults = config.getNodeFactory().objectNode();
56 Iterator<SettableBeanProperty> propertyIterator = beanDeserializer.properties();
57 while (propertyIterator.hasNext()) {
58 SettableBeanProperty prop = propertyIterator.next();
59 Class<?> declaringClass = prop.getMember().getDeclaringClass();
60 String canonicalClassName = declaringClass.getCanonicalName();
61 if ((canonicalClassName != null) && globalDefaults.hasPath(canonicalClassName)) {
62 Config declarerDefaults = globalDefaults.getConfig(canonicalClassName);
63 String propertyName = prop.getName();
64 if (declarerDefaults.hasPath(propertyName)) {
65 ConfigValue defaultValue = declarerDefaults.getValue(propertyName);
66 JsonNode fieldDefault = Jackson.configConverter(defaultValue);
67 fieldDefaults.set(propertyName, fieldDefault);
68 }
69 }
70 }
71 return new CodecBeanDeserializer(beanDeserializer, fieldDefaults);
72 } else {
73 return deserializer;
74 }
75 }
76
77 @Override public JsonDeserializer<?> modifyEnumDeserializer(DeserializationConfig config,
78 JavaType type,
79 BeanDescription beanDesc,
80 JsonDeserializer<?> deserializer) {
81 if (deserializer instanceof DelegatingDeserializer) {
82 JsonDeserializer<?> delegatee = ((DelegatingDeserializer) deserializer).getDelegatee();
83 JsonDeserializer<?> replacementDelegatee = modifyEnumDeserializer(config, type, beanDesc, delegatee);
84 return deserializer.replaceDelegatee(replacementDelegatee);
85 } else if (modifyEnum && (deserializer instanceof EnumDeserializer)) {
86 return new CaseIgnoringEnumDeserializer((EnumDeserializer) deserializer);
87 } else {
88 return deserializer;
89 }
90 }
91 }