├── .gitignore ├── .travis.yml ├── README.md ├── pom.xml ├── profile.sh ├── release-notes ├── CREDITS └── VERSION ├── run.sh └── src ├── main ├── java │ └── com │ │ └── fasterxml │ │ └── jackson │ │ └── module │ │ └── afterburner │ │ ├── AfterburnerModule.java │ │ ├── PackageVersion.java.in │ │ ├── deser │ │ ├── BeanPropertyMutator.java │ │ ├── CreatorOptimizer.java │ │ ├── DeserializerModifier.java │ │ ├── OptimizedSettableBeanProperty.java │ │ ├── OptimizedValueInstantiator.java │ │ ├── PropertyMutatorCollector.java │ │ ├── SettableBooleanFieldProperty.java │ │ ├── SettableBooleanMethodProperty.java │ │ ├── SettableIntFieldProperty.java │ │ ├── SettableIntMethodProperty.java │ │ ├── SettableLongFieldProperty.java │ │ ├── SettableLongMethodProperty.java │ │ ├── SettableObjectFieldProperty.java │ │ ├── SettableObjectMethodProperty.java │ │ ├── SettableStringFieldProperty.java │ │ ├── SettableStringMethodProperty.java │ │ ├── SuperSonicBeanDeserializer.java │ │ └── SuperSonicDeserializerBuilder.java │ │ ├── ser │ │ ├── BeanPropertyAccessor.java │ │ ├── BooleanFieldPropertyWriter.java │ │ ├── BooleanMethodPropertyWriter.java │ │ ├── IntFieldPropertyWriter.java │ │ ├── IntMethodPropertyWriter.java │ │ ├── LongFieldPropertyWriter.java │ │ ├── LongMethodPropertyWriter.java │ │ ├── ObjectFieldPropertyWriter.java │ │ ├── ObjectMethodPropertyWriter.java │ │ ├── OptimizedBeanPropertyWriter.java │ │ ├── PropertyAccessorCollector.java │ │ ├── SerializerModifier.java │ │ ├── StringFieldPropertyWriter.java │ │ └── StringMethodPropertyWriter.java │ │ └── util │ │ ├── ClassName.java │ │ ├── DynamicPropertyAccessorBase.java │ │ └── MyClassLoader.java └── resources │ └── META-INF │ ├── LICENSE │ └── services │ └── com.fasterxml.jackson.databind.Module └── test ├── java ├── com │ └── fasterxml │ │ └── jackson │ │ └── module │ │ └── afterburner │ │ ├── AfterburnerTestBase.java │ │ ├── TestAccessFallback.java │ │ ├── TestSealedPackages.java │ │ ├── TestUnwrapped.java │ │ ├── TestVersions.java │ │ ├── codegen │ │ └── GenerateWithMixinsTest.java │ │ ├── deser │ │ ├── TestBuilders.java │ │ ├── TestCollectionDeser.java │ │ ├── TestConstructors.java │ │ ├── TestCreators.java │ │ ├── TestCreators2.java │ │ ├── TestCreatorsDelegating.java │ │ ├── TestFinalFields.java │ │ ├── TestIssue14.java │ │ ├── TestNonStaticInner.java │ │ ├── TestPolymorphic.java │ │ ├── TestPolymorphicCreators.java │ │ ├── TestSimpleDeserialize.java │ │ ├── TestSingleArgCtors.java │ │ ├── TestStdDeserializerOverrides.java │ │ └── TestTreeConversions.java │ │ ├── roundtrip │ │ ├── AbstractSettersTest.java │ │ ├── BiggerDataTest.java │ │ ├── JavaxTypesTest.java │ │ ├── MediaItem.java │ │ ├── MediaItemRoundtripTest.java │ │ └── POJOAsArrayTest.java │ │ ├── ser │ │ ├── CustomBeanPropertyWriterTest.java │ │ ├── JsonAppendTest.java │ │ ├── JsonIncludeTest.java │ │ ├── SerializeWithViewTest.java │ │ ├── TestAccessorGeneration.java │ │ ├── TestInclusionAnnotations.java │ │ ├── TestInterfaceSerialize.java │ │ ├── TestJsonFilter.java │ │ ├── TestJsonSerializeAnnotationBug.java │ │ ├── TestRawValues.java │ │ ├── TestSimpleSerialize.java │ │ └── TestStdSerializerOverrides.java │ │ └── util │ │ └── MyClassLoaderTest.java ├── perf │ ├── ManualDatabindPerf.java │ ├── MediaItem.java │ ├── NopOutputStream.java │ ├── TestPojo.java │ └── Value.java └── perftest │ ├── MediaItem.java │ ├── TestDeserializePerf.java │ ├── TestJvmDeserPerf.java │ ├── TestJvmSerPerf.java │ └── TestSerializePerf.java └── resources └── data └── citm_catalog.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Skip maven 'target' directory 2 | target 3 | *~ 4 | 5 | # plus eclipse crap 6 | .classpath 7 | .project 8 | .settings 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - oraclejdk7 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **NOTE**: This module has moved under [jackson-modules-base](../../../jackson-modules-base) as of Jackson 2.7.1. 2 | 3 | This repo only exists for 2.6 patch releases. 4 | 5 | ----- 6 | 7 | Module that will add dynamic bytecode generation for standard Jackson POJO serializers and deserializers, eliminating majority of remaining data binding overhead. 8 | 9 | Plugs in using standard Module interface (requiring Jackson 2.0.0 or above). 10 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | com.fasterxml.jackson 5 | jackson-parent 6 | 2.7 7 | 8 | com.fasterxml.jackson.module 9 | jackson-module-afterburner 10 | Jackson-module-Afterburner 11 | 2.7.2-SNAPSHOT 12 | bundle 13 | Jackson (https://github.com/FasterXML/jackson) extension module 14 | used to enhance access functionality using bytecode generation. 15 | 16 | http://wiki.fasterxml.com/JacksonHome 17 | 18 | scm:git:git@github.com:FasterXML/jackson-module-afterburner.git 19 | scm:git:git@github.com:FasterXML/jackson-module-afterburner.git 20 | http://github.com/FasterXML/jackson-module-afterburner 21 | HEAD 22 | 23 | 24 | 25 | 2.7.1 26 | 27 | 28 | com/fasterxml/jackson/module/afterburner 29 | ${project.groupId}.afterburner 30 | 31 | 33 | 34 | 39 | org.objectweb.asm;resolution:=optional, 40 | * 41 | 42 | 45 | 46 | 47 | 48 | 51 | 52 | com.fasterxml.jackson.core 53 | jackson-core 54 | ${jackson.core.version} 55 | 56 | 57 | com.fasterxml.jackson.core 58 | jackson-databind 59 | ${jackson.core.version} 60 | 61 | 62 | org.ow2.asm 63 | asm 64 | 5.0.3 65 | compile 66 | 67 | 68 | com.fasterxml.jackson.core 69 | jackson-annotations 70 | test 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | com.google.code.maven-replacer-plugin 79 | replacer 80 | 81 | 82 | process-packageVersion 83 | generate-sources 84 | 85 | 86 | 87 | 88 | 89 | 90 | org.apache.maven.plugins 91 | maven-surefire-plugin 92 | ${version.plugin.surefire} 93 | 94 | 95 | com/fasterxml/jackson/**/failing/*.java 96 | 97 | 98 | 99 | 100 | 101 | 102 | org.apache.maven.plugins 103 | maven-shade-plugin 104 | 2.3 105 | 106 | 107 | package 108 | 109 | shade 110 | 111 | 112 | 113 | 114 | org.ow2.asm:asm 115 | 116 | 117 | 118 | 119 | org.objectweb.asm 120 | com.fasterxml.jackson.module.afterburner.asm 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /profile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | java -Xmx64m -server -cp lib/\*:target/\*:target/test-classes \ 4 | -Xrunhprof:cpu=samples,depth=10,verbose=n,interval=2 \ 5 | $* 6 | -------------------------------------------------------------------------------- /release-notes/CREDITS: -------------------------------------------------------------------------------- 1 | Here are people who have contributed to development Jackson JSON processor 2 | Afterburner component, version 2.x 3 | (version numbers in brackets indicate release in which the problem was fixed) 4 | 5 | (note: for older credits, check out release notes for 1.x versions) 6 | 7 | Tatu Saloranta, tatu.saloranta@iki.fi: author 8 | Steven Schlansker, co-author (numerous fixes, patches) 9 | 10 | celkings@github: 11 | 12 | * Reported [#22]: Problems with Builder-style deserialization 13 | (2.2.2) 14 | 15 | R.W Bergstom (rwbergstom@github) 16 | 17 | * Reported, contributed [#29]: NON_DEFAULT inclusion setting ignored by primitive 18 | writers 19 | (2.2.3) 20 | 21 | Nándor István Krácser (bonifaido@github) 22 | 23 | * Contributed #27/#23: ability to deserialize interface types 24 | (2.2.3) 25 | 26 | Joost van de Wijgerd (jwijgerd@github) 27 | 28 | * Contributed fix to #48: Problem passing custom `JsonSerializer`, causing an NPE 29 | (2.4.5) 30 | 31 | Jörn Huxhorn (huxi@github) 32 | 33 | * Reported #47: java.lang.VerifyError (Illegal type in constant pool ...) 34 | (2.5.1) 35 | 36 | natnan@github 37 | 38 | * Reported #52: Invalidating SerializationInclusion.NON_NULL of other modules 39 | (2.5.2) 40 | 41 | Steve Metcalfe (steveme@github) 42 | * Reported #58: Specific ordering of type information for polymorphic deserialization 43 | (2.6.2) 44 | 45 | Lucas Pouzac (lucaspouzac@github) 46 | 47 | * Reported, constributed fix to #63: Revert back expansion of NON_EMPTY handling 48 | (2.7.1) 49 | -------------------------------------------------------------------------------- /release-notes/VERSION: -------------------------------------------------------------------------------- 1 | Project: jackson-module-afterburner 2 | 3 | ------------------------------------------------------------------------ 4 | === Releases === 5 | ------------------------------------------------------------------------ 6 | 7 | 2.7.1 (02-Feb-2016) 8 | 9 | #63: Revert back expansion of NON_EMPTY handling 10 | (reported by Lucas P) 11 | 12 | 2.7.0 (10-Jan-2016) 13 | 14 | No changes since 2.6. 15 | 16 | 2.6.7.1 (not yet released) 17 | 18 | (modules-base#7): Afterburner excludes serialization of some `null`-valued 19 | Object properties 20 | 21 | 2.6.7 (05-Jun-2016) 22 | 2.6.6 (05-Apr-2016) 23 | 2.6.5 (19-Jan-2016) 24 | 2.6.4 (07-Dec-2015) 25 | 26 | No changes since 2.6.3 27 | 28 | 2.6.3 (12-Oct-2015) 29 | 30 | #59: Cannot customize String deserialization behavior 31 | (reported by brianwyantora@github) 32 | #60: Cannot read some "pretty" documents (NOTE: actually fixed by [jackson-core#220] in 2.6.3) 33 | (reported by lehcim@github) 34 | 35 | 2.6.2 (15-Sep-2015) 36 | 37 | #56: Afterburner does not respect DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS 38 | (reported by shollander@github) 39 | #57: `@JsonAppend` causes `NullPointerException` 40 | (reported by cleiner@github) 41 | #58: Specific ordering of type information for polymorphic deserialization 42 | (reported by Steve M) 43 | 44 | 2.6.1 (09-Aug-2015) 45 | 46 | No changes since 2.6.0 47 | 48 | 2.6.0 (19-Jul-2015) 49 | 50 | #46: Log-warning "Disabling Afterburner deserialization for type" using wrong logger-name 51 | #53: Include checksum in generated class names (to resolve #52) 52 | 53 | 2.5.4 (09-Jun-2015) 54 | 2.5.3 (24-Apr-2015) 55 | 2.5.2 (29-Mar-2015) 56 | 57 | No changes since 2.5.1 58 | 59 | 2.5.1 (06-Feb-2015) 60 | 61 | #47: java.lang.VerifyError (Illegal type in constant pool ...) 62 | (reported by huxi@github) 63 | #52: Invalidating SerializationInclusion.NON_NULL of other modules 64 | (reported by natnan@github) 65 | 66 | 2.5.0 (01-Jan-2015) 67 | 68 | - Remove coupling of `_name` field of `BeanPropertyWriter` 69 | 70 | 2.4.5 (not yet released) 71 | 72 | #48: Problem passing custom `JsonSerializer`, causing an NPE 73 | (reported, fix contributed by Joost v-d-W) 74 | 75 | 2.4.4 (24-Nov-2014) 76 | 77 | No changes since 2.4.3. 78 | 79 | 2.4.3 (03-Oct-2014) 80 | 81 | #42: Problems trying to deserialize final fields 82 | #43: Problem deserializing type with one polymorphic property that 83 | uses inclusion of `As.EXTERNAL_PROPERTY` 84 | (reported by steveme@github) 85 | #44: Optimize `boolean` property access (read/write) 86 | - Upgrade to ASM 5.0 87 | - Change AfterburnerModule to directly extend Module, not SimpleModule 88 | 89 | 2.4.2 (14-Aug-2014) 90 | 91 | #40: Failure to deserialize non-static inner classes 92 | (reported by nigelzor@github) 93 | #41: Serialization of `javax.security.auth.AuthPermission` fails 94 | 95 | 2.4.1 (17-Jun-2014) 96 | 97 | - Make accessor class 'final' 98 | 99 | 2.4.0 (02-Jun-2014) 100 | 101 | #13: Upgrade to ASM5 102 | 103 | 2.3.2 (01-Mar-2014) 104 | 105 | #39: Afterburner does not respect JsonInclude.Include.NON_EMPTY 106 | (reported by mahileeb@github) 107 | 108 | 2.3.1 (28-Dec-2013) 109 | 110 | #38: Handling of @JsonRawValue broken (require 2.3.1 of jackson-databind for fix) 111 | (reported by willcheck@github) 112 | 113 | 2.3.0 (14-Nov-2013) 114 | 115 | #33: `SuperSonicBeanDeserializer` not working (missing optimization) 116 | #34: Needs to skip private creators, can not access even from sub-class. 117 | 118 | 119 | 2.2.3 (23-Aug-2013) 120 | 121 | #9: Ensure that `@JsonUnwrapped` handling still works 122 | #23: Support deserialization of interface types 123 | (contributed by bonifaido@github) 124 | #26: Use `java.util.logging` for logging warnings: it sucks, but is 125 | overridable, does not require a new dependency 126 | #29: NON_DEFAULT inclusion setting ignored by primitive writers 127 | (reported by rwbergstrom@github) 128 | 129 | 2.2.2 (27-May-2013) 130 | 131 | #20: Protect Afterburner against IllegalAccessError and SecurityException 132 | (contributed by Steven S) 133 | #22: Problems with Builder-style deserialization (actual bug in jackson-databind; 134 | requires 2.2.2 of databind) 135 | (reported by celkings@github) 136 | #24: Disable handling of interface types (for now) 137 | 138 | 2.2.1 (03-May-2013) 139 | 140 | #16: Problems with non-void setters, part 2 141 | (contributed by Steven S) 142 | #21: Prevent attempts to generate classes in sealed packages 143 | (contributed by Steven S) 144 | 145 | 2.2.0 (22-Apr-2013) 146 | 147 | #14: Problems deserializing a complex POJO with serialization inclusion of 148 | NotNull. 149 | 150 | 2.1.2 (04-Dec-2012) 151 | 152 | #11: problems with property-based @JsonCreator 153 | 154 | 2.1.1 (11-Nov-2012) 155 | 156 | #10: null String got coerced to "null" on deserialization 157 | 158 | 2.1.0 (08-Oct-2012) 159 | 160 | New minor version. No functional changes, but has to be updated to 161 | ensure that 2.1 core methods are covered. 162 | 163 | 2.0.6 (22-Sep-2012) 164 | 165 | Fixes: 166 | 167 | * [Issue-5] Failed to use setters that return something (non-void setters) 168 | (reported by chillenious@GH) 169 | * [Issue-6] Annotation-indicated (de)serializers were being overridden 170 | by Afterburner optimizer. 171 | 172 | 2.0.5 (27-Jul-2012) 173 | 174 | No fixes, just dependency updates. 175 | 176 | 2.0.4 (28-Jun-2012) 177 | 178 | No fixes, just dependency updates. 179 | 180 | 2.0.3: skipped 181 | 182 | 2.0.2 (14-May-2012) 183 | 184 | - No changes, updated dependencies. 185 | 186 | 2.0.0 (25-Mar-2012) 187 | 188 | - No new features; upgraded to work with core 2.0.0. 189 | 190 | [entries for versions 1.x and earlier not retained; refer to earlier releases) 191 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | java -Xmx64m -server -cp lib/\*:target/\*:target/test-classes $* 4 | 5 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/AfterburnerModule.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner; 2 | 3 | import com.fasterxml.jackson.core.Version; 4 | import com.fasterxml.jackson.databind.Module; 5 | import com.fasterxml.jackson.module.afterburner.ser.SerializerModifier; 6 | import com.fasterxml.jackson.module.afterburner.deser.DeserializerModifier; 7 | 8 | public class AfterburnerModule extends Module 9 | implements java.io.Serializable // is this necessary? 10 | { 11 | private static final long serialVersionUID = 1L; 12 | 13 | /* 14 | /********************************************************************** 15 | /* Configuration settings 16 | /********************************************************************** 17 | */ 18 | 19 | /** 20 | * Flag to indicate whether we will try to load generated classes using 21 | * same class loader as one that loaded class being accessed or not. 22 | * If not, we will use class loader that loaded this module. 23 | * Benefit of using value class loader is that 'protected' and 'package access' 24 | * properties can be accessed; otherwise only 'public' properties can 25 | * be accessed. 26 | *

27 | * By default this feature is enabled. 28 | */ 29 | protected boolean _cfgUseValueClassLoader = true; 30 | 31 | /** 32 | * Flag to indicate whether we should use an optimized sub-class of 33 | * {@link com.fasterxml.jackson.databind.deser.BeanDeserializer} or not. 34 | * Use of optimized version should further improve performance, but 35 | * it can be disabled in case it causes issues. 36 | *

37 | * By default this feature is enabled. 38 | */ 39 | protected boolean _cfgUseOptimizedBeanDeserializer = true; 40 | 41 | /* 42 | /********************************************************************** 43 | /* Basic life-cycle 44 | /********************************************************************** 45 | */ 46 | 47 | public AfterburnerModule() { } 48 | 49 | @Override 50 | public void setupModule(SetupContext context) 51 | { 52 | ClassLoader cl = _cfgUseValueClassLoader ? null : getClass().getClassLoader(); 53 | context.addBeanDeserializerModifier(new DeserializerModifier(cl, 54 | _cfgUseOptimizedBeanDeserializer)); 55 | context.addBeanSerializerModifier(new SerializerModifier(cl)); 56 | } 57 | 58 | @Override 59 | public String getModuleName() { 60 | return getClass().getSimpleName(); 61 | } 62 | 63 | @Override 64 | public Version version() { 65 | return PackageVersion.VERSION; 66 | } 67 | 68 | /* 69 | /********************************************************************** 70 | /* Config methods 71 | /********************************************************************** 72 | */ 73 | 74 | /** 75 | * Flag to indicate whether we will try to load generated classes using 76 | * same class loader as one that loaded class being accessed or not. 77 | * If not, we will use class loader that loaded this module. 78 | * Benefit of using value class loader is that 'protected' and 'package access' 79 | * properties can be accessed; otherwise only 'public' properties can 80 | * be accessed. 81 | *

82 | * By default this feature is enabled. 83 | */ 84 | public AfterburnerModule setUseValueClassLoader(boolean state) { 85 | _cfgUseValueClassLoader = state; 86 | return this; 87 | } 88 | 89 | public AfterburnerModule setUseOptimizedBeanDeserializer(boolean state) { 90 | _cfgUseOptimizedBeanDeserializer = state; 91 | return this; 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/PackageVersion.java.in: -------------------------------------------------------------------------------- 1 | package @package@; 2 | 3 | import com.fasterxml.jackson.core.Version; 4 | import com.fasterxml.jackson.core.Versioned; 5 | import com.fasterxml.jackson.core.util.VersionUtil; 6 | 7 | /** 8 | * Automatically generated from PackageVersion.java.in during 9 | * packageVersion-generate execution of maven-replacer-plugin in 10 | * pom.xml. 11 | */ 12 | public final class PackageVersion implements Versioned { 13 | public final static Version VERSION = VersionUtil.parseVersion( 14 | "@projectversion@", "@projectgroupid@", "@projectartifactid@"); 15 | 16 | @Override 17 | public Version version() { 18 | return VERSION; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/OptimizedValueInstantiator.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import com.fasterxml.jackson.databind.DeserializationContext; 7 | import com.fasterxml.jackson.databind.deser.std.StdValueInstantiator; 8 | 9 | /** 10 | * Base class for concrete bytecode-generated value instantiators. 11 | */ 12 | public abstract class OptimizedValueInstantiator 13 | extends StdValueInstantiator 14 | { 15 | private static final long serialVersionUID = 1L; 16 | 17 | /** 18 | * Default constructor which is only used when creating 19 | * dummy instance to call factory method. 20 | */ 21 | protected OptimizedValueInstantiator() { 22 | super(/*DeserializationConfig*/null, (Class)String.class); 23 | } 24 | 25 | /** 26 | * Copy-constructor to use for creating actual optimized instances. 27 | */ 28 | protected OptimizedValueInstantiator(StdValueInstantiator src) { 29 | super(src); 30 | } 31 | 32 | /** 33 | * Need to override this, now that we have installed default creator. 34 | */ 35 | @Override 36 | public boolean canCreateUsingDefault() { 37 | return true; 38 | } 39 | 40 | protected abstract OptimizedValueInstantiator with(StdValueInstantiator src); 41 | 42 | /* Define as abstract to ensure that it gets reimplemented; or if not, 43 | * we get a specific error (too easy to break, and get cryptic error) 44 | */ 45 | @Override 46 | public abstract Object createUsingDefault(DeserializationContext ctxt) 47 | throws IOException, JsonProcessingException; 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/SettableBooleanFieldProperty.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.databind.deser.SettableBeanProperty; 8 | 9 | public final class SettableBooleanFieldProperty 10 | extends OptimizedSettableBeanProperty 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public SettableBooleanFieldProperty(SettableBeanProperty src, 15 | BeanPropertyMutator mutator, int index) 16 | { 17 | super(src, mutator, index); 18 | } 19 | 20 | public SettableBooleanFieldProperty(SettableBooleanFieldProperty src, 21 | JsonDeserializer deser) 22 | { 23 | super(src, deser); 24 | } 25 | 26 | public SettableBooleanFieldProperty(SettableBooleanFieldProperty src, PropertyName name) { 27 | super(src, name); 28 | } 29 | 30 | @Override 31 | public SettableBeanProperty withName(PropertyName name) { 32 | return new SettableBooleanFieldProperty(this, name); 33 | } 34 | 35 | @Override 36 | public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { 37 | if (!_isDefaultDeserializer(deser)) { 38 | return _originalSettable.withValueDeserializer(deser); 39 | } 40 | return new SettableBooleanFieldProperty(this, deser); 41 | } 42 | 43 | @Override 44 | public SettableBeanProperty withMutator(BeanPropertyMutator mut) { 45 | return new SettableBooleanFieldProperty(_originalSettable, mut, _optimizedIndex); 46 | } 47 | 48 | /* 49 | /********************************************************************** 50 | /* Deserialization 51 | /********************************************************************** 52 | */ 53 | 54 | @Override 55 | public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException { 56 | boolean b; 57 | JsonToken t = p.getCurrentToken(); 58 | if (t == JsonToken.VALUE_TRUE) { 59 | b = true; 60 | } else if (t == JsonToken.VALUE_FALSE) { 61 | b = false; 62 | } else { 63 | b = _deserializeBoolean(p, ctxt); 64 | } 65 | _propertyMutator.booleanField(bean, b); 66 | } 67 | 68 | @Override 69 | public void set(Object bean, Object value) throws IOException { 70 | // not optimal (due to boxing), but better than using reflection: 71 | _propertyMutator.booleanField(bean, ((Boolean) value).booleanValue()); 72 | } 73 | 74 | @Override 75 | public Object deserializeSetAndReturn(JsonParser p, 76 | DeserializationContext ctxt, Object instance) throws IOException 77 | { 78 | boolean b; 79 | JsonToken t = p.getCurrentToken(); 80 | if (t == JsonToken.VALUE_TRUE) { 81 | b = true; 82 | } else if (t == JsonToken.VALUE_FALSE) { 83 | b = false; 84 | } else { 85 | b = _deserializeBoolean(p, ctxt); 86 | } 87 | return setAndReturn(instance, b); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/SettableBooleanMethodProperty.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.databind.deser.SettableBeanProperty; 8 | 9 | public final class SettableBooleanMethodProperty 10 | extends OptimizedSettableBeanProperty 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public SettableBooleanMethodProperty(SettableBeanProperty src, 15 | BeanPropertyMutator mutator, int index) 16 | { 17 | super(src, mutator, index); 18 | } 19 | 20 | public SettableBooleanMethodProperty(SettableBooleanMethodProperty src, JsonDeserializer deser) { 21 | super(src, deser); 22 | } 23 | 24 | public SettableBooleanMethodProperty(SettableBooleanMethodProperty src, PropertyName name) { 25 | super(src, name); 26 | } 27 | 28 | @Override 29 | public SettableBeanProperty withName(PropertyName name) { 30 | return new SettableBooleanMethodProperty(this, name); 31 | } 32 | 33 | @Override 34 | public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { 35 | if (!_isDefaultDeserializer(deser)) { 36 | return _originalSettable.withValueDeserializer(deser); 37 | } 38 | return new SettableBooleanMethodProperty(this, deser); 39 | } 40 | 41 | @Override 42 | public SettableBeanProperty withMutator(BeanPropertyMutator mut) { 43 | return new SettableBooleanMethodProperty(_originalSettable, mut, _optimizedIndex); 44 | } 45 | 46 | /* 47 | /********************************************************************** 48 | /* Deserialization 49 | /********************************************************************** 50 | */ 51 | 52 | @Override 53 | public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException { 54 | boolean b; 55 | JsonToken t = p.getCurrentToken(); 56 | if (t == JsonToken.VALUE_TRUE) { 57 | b = true; 58 | } else if (t == JsonToken.VALUE_FALSE) { 59 | b = false; 60 | } else { 61 | b = _deserializeBoolean(p, ctxt); 62 | } 63 | _propertyMutator.booleanSetter(bean, b); 64 | } 65 | 66 | @Override 67 | public void set(Object bean, Object value) throws IOException { 68 | // not optimal (due to boxing), but better than using reflection: 69 | _propertyMutator.booleanSetter(bean, ((Boolean) value).booleanValue()); 70 | } 71 | 72 | @Override 73 | public Object deserializeSetAndReturn(JsonParser p, 74 | DeserializationContext ctxt, Object instance) throws IOException 75 | { 76 | boolean b; 77 | JsonToken t = p.getCurrentToken(); 78 | if (t == JsonToken.VALUE_TRUE) { 79 | b = true; 80 | } else if (t == JsonToken.VALUE_FALSE) { 81 | b = false; 82 | } else { 83 | b = _deserializeBoolean(p, ctxt); 84 | } 85 | return setAndReturn(instance, b); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/SettableIntFieldProperty.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.databind.deser.SettableBeanProperty; 8 | 9 | public final class SettableIntFieldProperty 10 | extends OptimizedSettableBeanProperty 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public SettableIntFieldProperty(SettableBeanProperty src, 15 | BeanPropertyMutator mutator, int index) 16 | { 17 | super(src, mutator, index); 18 | } 19 | 20 | public SettableIntFieldProperty(SettableIntFieldProperty src, 21 | JsonDeserializer deser) 22 | { 23 | super(src, deser); 24 | } 25 | 26 | public SettableIntFieldProperty(SettableIntFieldProperty src, PropertyName name) { 27 | super(src, name); 28 | } 29 | 30 | @Override 31 | public SettableBeanProperty withName(PropertyName name) { 32 | return new SettableIntFieldProperty(this, name); 33 | } 34 | 35 | @Override 36 | public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { 37 | if (!_isDefaultDeserializer(deser)) { 38 | return _originalSettable.withValueDeserializer(deser); 39 | } 40 | return new SettableIntFieldProperty(this, deser); 41 | } 42 | 43 | @Override 44 | public SettableBeanProperty withMutator(BeanPropertyMutator mut) { 45 | return new SettableIntFieldProperty(_originalSettable, mut, _optimizedIndex); 46 | } 47 | 48 | /* 49 | /********************************************************************** 50 | /* Deserialization 51 | /********************************************************************** 52 | */ 53 | 54 | @Override 55 | public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, 56 | Object bean) throws IOException 57 | { 58 | int v = p.hasToken(JsonToken.VALUE_NUMBER_INT) ? p.getIntValue() : _deserializeInt(p, ctxt); 59 | _propertyMutator.intField(bean, v); 60 | } 61 | 62 | @Override 63 | public void set(Object bean, Object value) throws IOException { 64 | // not optimal (due to boxing), but better than using reflection: 65 | _propertyMutator.intField(bean, ((Number) value).intValue()); 66 | } 67 | 68 | @Override 69 | public Object deserializeSetAndReturn(JsonParser p, 70 | DeserializationContext ctxt, Object instance) throws IOException 71 | { 72 | int v = p.hasToken(JsonToken.VALUE_NUMBER_INT) ? p.getIntValue() : _deserializeInt(p, ctxt); 73 | return setAndReturn(instance, v); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/SettableIntMethodProperty.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.databind.deser.SettableBeanProperty; 8 | 9 | public final class SettableIntMethodProperty 10 | extends OptimizedSettableBeanProperty 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public SettableIntMethodProperty(SettableBeanProperty src, 15 | BeanPropertyMutator mutator, int index) 16 | { 17 | super(src, mutator, index); 18 | } 19 | 20 | public SettableIntMethodProperty(SettableIntMethodProperty src, JsonDeserializer deser) { 21 | super(src, deser); 22 | } 23 | 24 | public SettableIntMethodProperty(SettableIntMethodProperty src, PropertyName name) { 25 | super(src, name); 26 | } 27 | 28 | @Override 29 | public SettableBeanProperty withName(PropertyName name) { 30 | return new SettableIntMethodProperty(this, name); 31 | } 32 | 33 | @Override 34 | public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { 35 | if (!_isDefaultDeserializer(deser)) { 36 | return _originalSettable.withValueDeserializer(deser); 37 | } 38 | return new SettableIntMethodProperty(this, deser); 39 | } 40 | 41 | @Override 42 | public SettableBeanProperty withMutator(BeanPropertyMutator mut) { 43 | return new SettableIntMethodProperty(_originalSettable, mut, _optimizedIndex); 44 | } 45 | 46 | /* 47 | /********************************************************************** 48 | /* Deserialization 49 | /********************************************************************** 50 | */ 51 | 52 | @Override 53 | public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, 54 | Object bean) throws IOException 55 | { 56 | int v = p.hasToken(JsonToken.VALUE_NUMBER_INT) ? p.getIntValue() : _deserializeInt(p, ctxt); 57 | _propertyMutator.intSetter(bean, v); 58 | } 59 | 60 | @Override 61 | public void set(Object bean, Object value) throws IOException { 62 | // not optimal (due to boxing), but better than using reflection: 63 | _propertyMutator.intSetter(bean, ((Number) value).intValue()); 64 | } 65 | 66 | @Override 67 | public Object deserializeSetAndReturn(JsonParser p, 68 | DeserializationContext ctxt, Object instance) 69 | throws IOException 70 | { 71 | int v = p.hasToken(JsonToken.VALUE_NUMBER_INT) ? p.getIntValue() : _deserializeInt(p, ctxt); 72 | return setAndReturn(instance, v); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/SettableLongFieldProperty.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.databind.deser.SettableBeanProperty; 8 | 9 | public final class SettableLongFieldProperty 10 | extends OptimizedSettableBeanProperty 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public SettableLongFieldProperty(SettableBeanProperty src, 15 | BeanPropertyMutator mutator, int index) 16 | { 17 | super(src, mutator, index); 18 | } 19 | 20 | public SettableLongFieldProperty(SettableLongFieldProperty src, JsonDeserializer deser) { 21 | super(src, deser); 22 | } 23 | 24 | public SettableLongFieldProperty(SettableLongFieldProperty src, PropertyName name) { 25 | super(src, name); 26 | } 27 | 28 | @Override 29 | public SettableBeanProperty withName(PropertyName name) { 30 | return new SettableLongFieldProperty(this, name); 31 | } 32 | 33 | @Override 34 | public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { 35 | if (!_isDefaultDeserializer(deser)) { 36 | return _originalSettable.withValueDeserializer(deser); 37 | } 38 | return new SettableLongFieldProperty(this, deser); 39 | } 40 | 41 | @Override 42 | public SettableBeanProperty withMutator(BeanPropertyMutator mut) { 43 | return new SettableLongFieldProperty(_originalSettable, mut, _optimizedIndex); 44 | } 45 | 46 | /* 47 | /********************************************************************** 48 | /* Deserialization 49 | /********************************************************************** 50 | */ 51 | 52 | @Override 53 | public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, 54 | Object bean) throws IOException 55 | { 56 | long l = p.hasToken(JsonToken.VALUE_NUMBER_INT) ? p.getLongValue() : _deserializeLong(p, ctxt); 57 | _propertyMutator.longField(bean, l); 58 | } 59 | 60 | @Override 61 | public void set(Object bean, Object value) throws IOException { 62 | // not optimal (due to boxing), but better than using reflection: 63 | _propertyMutator.longField(bean, ((Number) value).longValue()); 64 | } 65 | 66 | @Override 67 | public Object deserializeSetAndReturn(JsonParser p, 68 | DeserializationContext ctxt, Object instance) throws IOException 69 | { 70 | long l = p.hasToken(JsonToken.VALUE_NUMBER_INT) ? p.getLongValue() : _deserializeLong(p, ctxt); 71 | return setAndReturn(instance, l); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/SettableLongMethodProperty.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.databind.deser.SettableBeanProperty; 8 | 9 | public final class SettableLongMethodProperty 10 | extends OptimizedSettableBeanProperty 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public SettableLongMethodProperty(SettableBeanProperty src, 15 | BeanPropertyMutator mutator, int index) 16 | { 17 | super(src, mutator, index); 18 | } 19 | 20 | public SettableLongMethodProperty(SettableLongMethodProperty src, JsonDeserializer deser) { 21 | super(src, deser); 22 | } 23 | 24 | public SettableLongMethodProperty(SettableLongMethodProperty src, PropertyName name) { 25 | super(src, name); 26 | } 27 | 28 | @Override 29 | public SettableBeanProperty withName(PropertyName name) { 30 | return new SettableLongMethodProperty(this, name); 31 | } 32 | 33 | @Override 34 | public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { 35 | if (!_isDefaultDeserializer(deser)) { 36 | return _originalSettable.withValueDeserializer(deser); 37 | } 38 | return new SettableLongMethodProperty(this, deser); 39 | } 40 | 41 | @Override 42 | public SettableBeanProperty withMutator(BeanPropertyMutator mut) { 43 | return new SettableLongMethodProperty(_originalSettable, mut, _optimizedIndex); 44 | } 45 | 46 | /* 47 | /********************************************************************** 48 | /* Deserialization 49 | /********************************************************************** 50 | */ 51 | 52 | @Override 53 | public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, 54 | Object bean) throws IOException 55 | { 56 | long l = p.hasToken(JsonToken.VALUE_NUMBER_INT) ? p.getLongValue() : _deserializeLong(p, ctxt); 57 | _propertyMutator.longSetter(bean, l); 58 | } 59 | 60 | @Override 61 | public void set(Object bean, Object value) throws IOException { 62 | // not optimal (due to boxing), but better than using reflection: 63 | _propertyMutator.longSetter(bean, ((Number) value).longValue()); 64 | } 65 | 66 | @Override 67 | public Object deserializeSetAndReturn(JsonParser p, 68 | DeserializationContext ctxt, Object instance) throws IOException 69 | { 70 | long l = p.hasToken(JsonToken.VALUE_NUMBER_INT) ? p.getLongValue() : _deserializeLong(p, ctxt); 71 | return setAndReturn(instance, l); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/SettableObjectFieldProperty.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.databind.deser.SettableBeanProperty; 8 | 9 | public final class SettableObjectFieldProperty 10 | extends OptimizedSettableBeanProperty 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public SettableObjectFieldProperty(SettableBeanProperty src, 15 | BeanPropertyMutator mutator, int index) 16 | { 17 | super(src, mutator, index); 18 | } 19 | 20 | public SettableObjectFieldProperty(SettableObjectFieldProperty src, JsonDeserializer deser) { 21 | super(src, deser); 22 | } 23 | 24 | public SettableObjectFieldProperty(SettableObjectFieldProperty src, PropertyName name) { 25 | super(src, name); 26 | } 27 | 28 | @Override 29 | public SettableBeanProperty withName(PropertyName name) { 30 | return new SettableObjectFieldProperty(this, name); 31 | } 32 | 33 | @Override 34 | public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { 35 | if (!_isDefaultDeserializer(deser)) { 36 | return _originalSettable.withValueDeserializer(deser); 37 | } 38 | return new SettableObjectFieldProperty(this, deser); 39 | } 40 | 41 | @Override 42 | public SettableBeanProperty withMutator(BeanPropertyMutator mut) { 43 | return new SettableObjectFieldProperty(_originalSettable, mut, _optimizedIndex); 44 | } 45 | 46 | /* 47 | /********************************************************************** 48 | /* Deserialization 49 | /********************************************************************** 50 | */ 51 | 52 | @Override 53 | public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, 54 | Object bean) throws IOException 55 | { 56 | set(bean, deserialize(p, ctxt)); 57 | } 58 | 59 | @Override 60 | public void set(Object bean, Object value) throws IOException { 61 | _propertyMutator.objectField(bean, value); 62 | } 63 | 64 | @Override 65 | public Object deserializeSetAndReturn(JsonParser p, 66 | DeserializationContext ctxt, Object instance) throws IOException 67 | { 68 | return setAndReturn(instance, deserialize(p, ctxt)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/SettableObjectMethodProperty.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.databind.deser.SettableBeanProperty; 8 | 9 | public final class SettableObjectMethodProperty 10 | extends OptimizedSettableBeanProperty 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public SettableObjectMethodProperty(SettableBeanProperty src, 15 | BeanPropertyMutator mutator, int index) 16 | { 17 | super(src, mutator, index); 18 | } 19 | 20 | public SettableObjectMethodProperty(SettableObjectMethodProperty src, JsonDeserializer deser) { 21 | super(src, deser); 22 | } 23 | 24 | public SettableObjectMethodProperty(SettableObjectMethodProperty src, PropertyName name) { 25 | super(src, name); 26 | } 27 | 28 | @Override 29 | public SettableBeanProperty withName(PropertyName name) { 30 | return new SettableObjectMethodProperty(this, name); 31 | } 32 | 33 | @Override 34 | public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { 35 | if (!_isDefaultDeserializer(deser)) { 36 | return _originalSettable.withValueDeserializer(deser); 37 | } 38 | return new SettableObjectMethodProperty(this, deser); 39 | } 40 | 41 | @Override 42 | public SettableBeanProperty withMutator(BeanPropertyMutator mut) { 43 | return new SettableObjectMethodProperty(_originalSettable, mut, _optimizedIndex); 44 | } 45 | 46 | /* 47 | /********************************************************************** 48 | /* Deserialization 49 | /********************************************************************** 50 | */ 51 | 52 | @Override 53 | public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, 54 | Object bean) throws IOException { 55 | set(bean, deserialize(p, ctxt)); 56 | } 57 | 58 | @Override 59 | public void set(Object bean, Object value) throws IOException { 60 | _propertyMutator.objectSetter(bean, value); 61 | } 62 | 63 | @Override 64 | public Object deserializeSetAndReturn(JsonParser p, 65 | DeserializationContext ctxt, Object instance) throws IOException { 66 | return setAndReturn(instance, deserialize(p, ctxt)); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/SettableStringFieldProperty.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.databind.deser.SettableBeanProperty; 8 | 9 | public final class SettableStringFieldProperty 10 | extends OptimizedSettableBeanProperty 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public SettableStringFieldProperty(SettableBeanProperty src, 15 | BeanPropertyMutator mutator, int index) 16 | { 17 | super(src, mutator, index); 18 | } 19 | 20 | public SettableStringFieldProperty(SettableStringFieldProperty src, JsonDeserializer deser) { 21 | super(src, deser); 22 | } 23 | 24 | public SettableStringFieldProperty(SettableStringFieldProperty src, PropertyName name) { 25 | super(src, name); 26 | } 27 | 28 | @Override 29 | public SettableBeanProperty withName(PropertyName name) { 30 | return new SettableStringFieldProperty(this, name); 31 | } 32 | 33 | @Override 34 | public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { 35 | if (!_isDefaultDeserializer(deser)) { 36 | return _originalSettable.withValueDeserializer(deser); 37 | } 38 | return new SettableStringFieldProperty(this, deser); 39 | } 40 | 41 | @Override 42 | public SettableBeanProperty withMutator(BeanPropertyMutator mut) { 43 | return new SettableStringFieldProperty(_originalSettable, mut, _optimizedIndex); 44 | } 45 | 46 | /* 47 | /********************************************************************** 48 | /* Deserialization 49 | /********************************************************************** 50 | */ 51 | 52 | @Override 53 | public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, 54 | Object bean) throws IOException 55 | { 56 | String text = p.getValueAsString(); 57 | if (text == null) { 58 | text = _deserializeString(p, ctxt); 59 | } 60 | _propertyMutator.stringField(bean, text); 61 | } 62 | 63 | @Override 64 | public void set(Object bean, Object value) throws IOException { 65 | _propertyMutator.stringField(bean, (String) value); 66 | } 67 | 68 | @Override 69 | public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) 70 | throws IOException 71 | { 72 | String text = p.getValueAsString(); 73 | if (text == null) { 74 | text = _deserializeString(p, ctxt); 75 | } 76 | return setAndReturn(instance, text); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/SettableStringMethodProperty.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.databind.deser.SettableBeanProperty; 8 | 9 | public final class SettableStringMethodProperty 10 | extends OptimizedSettableBeanProperty 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public SettableStringMethodProperty(SettableBeanProperty src, 15 | BeanPropertyMutator mutator, int index) 16 | { 17 | super(src, mutator, index); 18 | } 19 | 20 | public SettableStringMethodProperty(SettableStringMethodProperty src, JsonDeserializer deser) { 21 | super(src, deser); 22 | } 23 | 24 | public SettableStringMethodProperty(SettableStringMethodProperty src, PropertyName name) { 25 | super(src, name); 26 | } 27 | 28 | @Override 29 | public SettableBeanProperty withName(PropertyName name) { 30 | return new SettableStringMethodProperty(this, name); 31 | } 32 | 33 | @Override 34 | public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { 35 | if (!_isDefaultDeserializer(deser)) { 36 | return _originalSettable.withValueDeserializer(deser); 37 | } 38 | return new SettableStringMethodProperty(this, deser); 39 | } 40 | 41 | @Override 42 | public SettableBeanProperty withMutator(BeanPropertyMutator mut) { 43 | return new SettableStringMethodProperty(_originalSettable, mut, _optimizedIndex); 44 | } 45 | 46 | /* 47 | /********************************************************************** 48 | /* Deserialization 49 | /********************************************************************** 50 | */ 51 | 52 | // Copied from StdDeserializer.StringDeserializer: 53 | @Override 54 | public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException 55 | { 56 | String text = p.getValueAsString(); 57 | if (text == null) { 58 | text = _deserializeString(p, ctxt); 59 | } 60 | _propertyMutator.stringSetter(bean, text); 61 | } 62 | 63 | @Override 64 | public void set(Object bean, Object value) throws IOException { 65 | _propertyMutator.stringSetter(bean, (String) value); 66 | } 67 | 68 | @Override 69 | public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance) throws IOException 70 | { 71 | String text = p.getValueAsString(); 72 | if (text == null) { 73 | text = _deserializeString(p, ctxt); 74 | } 75 | return setAndReturn(instance, text); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/deser/SuperSonicDeserializerBuilder.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.util.*; 4 | 5 | import com.fasterxml.jackson.databind.JsonDeserializer; 6 | import com.fasterxml.jackson.databind.deser.*; 7 | 8 | public class SuperSonicDeserializerBuilder extends BeanDeserializerBuilder 9 | { 10 | public SuperSonicDeserializerBuilder(BeanDeserializerBuilder base) { 11 | super(base); 12 | } 13 | 14 | @Override 15 | public JsonDeserializer build() 16 | { 17 | BeanDeserializer deser = (BeanDeserializer) super.build(); 18 | // only create custom one, if existing one is standard deserializer; 19 | if (deser.getClass() == BeanDeserializer.class) { 20 | BeanDeserializer beanDeser = (BeanDeserializer) deser; 21 | Iterator it = getProperties(); 22 | // also: only build custom one for non-empty beans: 23 | if (it.hasNext()) { 24 | // So let's find actual order of properties, necessary for optimal access 25 | ArrayList props = new ArrayList(); 26 | do { 27 | props.add(it.next()); 28 | } while (it.hasNext()); 29 | return new SuperSonicBeanDeserializer(beanDeser, props); 30 | } 31 | } 32 | return deser; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/BeanPropertyAccessor.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | /** 4 | * Abstract class that defines interface for implementations 5 | * that can be used for proxy-like access without using 6 | * Reflection. 7 | */ 8 | public abstract class BeanPropertyAccessor 9 | { 10 | /** @since 2.5 */ 11 | public boolean booleanGetter(Object bean, int property) { 12 | throw new UnsupportedOperationException("No booleanGetters defined"); 13 | } 14 | public int intGetter(Object bean, int property) { 15 | throw new UnsupportedOperationException("No intGetters defined"); 16 | } 17 | public long longGetter(Object bean, int property) { 18 | throw new UnsupportedOperationException("No longGetters defined"); 19 | } 20 | public String stringGetter(Object bean, int property) { 21 | throw new UnsupportedOperationException("No stringGetters defined"); 22 | } 23 | public Object objectGetter(Object bean, int property) { 24 | throw new UnsupportedOperationException("No objectGetters defined"); 25 | } 26 | 27 | /** @since 2.5 */ 28 | public boolean booleanField(Object bean, int property) { 29 | throw new UnsupportedOperationException("No booleanFields defined"); 30 | } 31 | public int intField(Object bean, int property) { 32 | throw new UnsupportedOperationException("No intFields defined"); 33 | } 34 | public long longField(Object bean, int property) { 35 | throw new UnsupportedOperationException("No longFields defined"); 36 | } 37 | public String stringField(Object bean, int property) { 38 | throw new UnsupportedOperationException("No stringFields defined"); 39 | } 40 | public Object objectField(Object bean, int property) { 41 | throw new UnsupportedOperationException("No objectFields defined"); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/BooleanFieldPropertyWriter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.JsonSerializer; 5 | import com.fasterxml.jackson.databind.SerializerProvider; 6 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 7 | 8 | public final class BooleanFieldPropertyWriter 9 | extends OptimizedBeanPropertyWriter 10 | { 11 | private static final long serialVersionUID = 1L; 12 | 13 | private final boolean _suppressableSet; 14 | private final boolean _suppressableBoolean; 15 | 16 | public BooleanFieldPropertyWriter(BeanPropertyWriter src, BeanPropertyAccessor acc, int index, 17 | JsonSerializer ser) { 18 | super(src, acc, index, ser); 19 | 20 | if (_suppressableValue instanceof Boolean) { 21 | _suppressableBoolean = ((Boolean)_suppressableValue).booleanValue(); 22 | _suppressableSet = true; 23 | } else { 24 | _suppressableBoolean = false; 25 | _suppressableSet = false; 26 | } 27 | } 28 | 29 | @Override 30 | public BeanPropertyWriter withSerializer(JsonSerializer ser) { 31 | return new BooleanFieldPropertyWriter(this, _propertyAccessor, _propertyIndex, ser); 32 | } 33 | 34 | @Override 35 | public BooleanFieldPropertyWriter withAccessor(BeanPropertyAccessor acc) { 36 | if (acc == null) throw new IllegalArgumentException(); 37 | return new BooleanFieldPropertyWriter(this, acc, _propertyIndex, _serializer); 38 | } 39 | 40 | /* 41 | /********************************************************** 42 | /* Overrides 43 | /********************************************************** 44 | */ 45 | 46 | @Override 47 | public final void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 48 | { 49 | if (broken) { 50 | fallbackWriter.serializeAsField(bean, gen, prov); 51 | return; 52 | } 53 | boolean value; 54 | try { 55 | value = _propertyAccessor.booleanField(bean, _propertyIndex); 56 | } catch (Throwable t) { 57 | _handleProblem(bean, gen, prov, t, false); 58 | return; 59 | } 60 | if (!_suppressableSet || _suppressableBoolean != value) { 61 | gen.writeFieldName(_fastName); 62 | gen.writeBoolean(value); 63 | } 64 | } 65 | 66 | @Override 67 | public final void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 68 | { 69 | if (broken) { 70 | fallbackWriter.serializeAsElement(bean, gen, prov); 71 | return; 72 | } 73 | boolean value; 74 | try { 75 | value = _propertyAccessor.booleanField(bean, _propertyIndex); 76 | } catch (Throwable t) { 77 | _handleProblem(bean, gen, prov, t, true); 78 | return; 79 | } 80 | if (!_suppressableSet || _suppressableBoolean != value) { 81 | gen.writeBoolean(value); 82 | } else { // important: MUST output a placeholder 83 | serializeAsPlaceholder(bean, gen, prov); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/BooleanMethodPropertyWriter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.JsonSerializer; 5 | import com.fasterxml.jackson.databind.SerializerProvider; 6 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 7 | 8 | public final class BooleanMethodPropertyWriter 9 | extends OptimizedBeanPropertyWriter 10 | { 11 | private static final long serialVersionUID = 1L; 12 | 13 | private final boolean _suppressableSet; 14 | private final boolean _suppressableBoolean; 15 | 16 | public BooleanMethodPropertyWriter(BeanPropertyWriter src, BeanPropertyAccessor acc, int index, 17 | JsonSerializer ser) { 18 | super(src, acc, index, ser); 19 | 20 | if (_suppressableValue instanceof Boolean) { 21 | _suppressableBoolean = ((Boolean)_suppressableValue).booleanValue(); 22 | _suppressableSet = true; 23 | } else { 24 | _suppressableBoolean = false; 25 | _suppressableSet = false; 26 | } 27 | } 28 | 29 | @Override 30 | public BeanPropertyWriter withSerializer(JsonSerializer ser) { 31 | return new BooleanMethodPropertyWriter(this, _propertyAccessor, _propertyIndex, ser); 32 | } 33 | 34 | @Override 35 | public BooleanMethodPropertyWriter withAccessor(BeanPropertyAccessor acc) { 36 | if (acc == null) throw new IllegalArgumentException(); 37 | return new BooleanMethodPropertyWriter(this, acc, _propertyIndex, _serializer); 38 | } 39 | 40 | /* 41 | /********************************************************** 42 | /* Overrides 43 | /********************************************************** 44 | */ 45 | 46 | @Override 47 | public final void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 48 | { 49 | if (broken) { 50 | fallbackWriter.serializeAsField(bean, gen, prov); 51 | return; 52 | } 53 | boolean value; 54 | try { 55 | value = _propertyAccessor.booleanGetter(bean, _propertyIndex); 56 | } catch (Throwable t) { 57 | _handleProblem(bean, gen, prov, t, false); 58 | return; 59 | } 60 | if (!_suppressableSet || _suppressableBoolean != value) { 61 | gen.writeFieldName(_fastName); 62 | gen.writeBoolean(value); 63 | } 64 | } 65 | 66 | @Override 67 | public final void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 68 | { 69 | if (broken) { 70 | fallbackWriter.serializeAsElement(bean, gen, prov); 71 | return; 72 | } 73 | boolean value; 74 | try { 75 | value = _propertyAccessor.booleanGetter(bean, _propertyIndex); 76 | } catch (Throwable t) { 77 | _handleProblem(bean, gen, prov, t, true); 78 | return; 79 | } 80 | if (!_suppressableSet || _suppressableBoolean != value) { 81 | gen.writeBoolean(value); 82 | } else { // important: MUST output a placeholder 83 | serializeAsPlaceholder(bean, gen, prov); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/IntFieldPropertyWriter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.JsonSerializer; 5 | import com.fasterxml.jackson.databind.SerializerProvider; 6 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 7 | 8 | public final class IntFieldPropertyWriter 9 | extends OptimizedBeanPropertyWriter 10 | { 11 | private static final long serialVersionUID = 1L; 12 | 13 | private final int _suppressableInt; 14 | private final boolean _suppressableIntSet; 15 | 16 | public IntFieldPropertyWriter(BeanPropertyWriter src, BeanPropertyAccessor acc, int index, 17 | JsonSerializer ser) { 18 | super(src, acc, index, ser); 19 | 20 | if (_suppressableValue instanceof Integer) { 21 | _suppressableInt = ((Integer)_suppressableValue).intValue(); 22 | _suppressableIntSet = true; 23 | } else { 24 | _suppressableInt = 0; 25 | _suppressableIntSet = false; 26 | } 27 | } 28 | 29 | @Override 30 | public BeanPropertyWriter withSerializer(JsonSerializer ser) { 31 | return new IntFieldPropertyWriter(this, _propertyAccessor, _propertyIndex, ser); 32 | } 33 | 34 | @Override 35 | public IntFieldPropertyWriter withAccessor(BeanPropertyAccessor acc) { 36 | if (acc == null) throw new IllegalArgumentException(); 37 | return new IntFieldPropertyWriter(this, acc, _propertyIndex, _serializer); 38 | } 39 | 40 | /* 41 | /********************************************************** 42 | /* Overrides 43 | /********************************************************** 44 | */ 45 | 46 | @Override 47 | public final void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 48 | { 49 | if (broken) { 50 | fallbackWriter.serializeAsField(bean, gen, prov); 51 | return; 52 | } 53 | int value; 54 | try { 55 | value = _propertyAccessor.intField(bean, _propertyIndex); 56 | } catch (Throwable t) { 57 | _handleProblem(bean, gen, prov, t, false); 58 | return; 59 | } 60 | if (!_suppressableIntSet || _suppressableInt != value) { 61 | gen.writeFieldName(_fastName); 62 | gen.writeNumber(value); 63 | } 64 | } 65 | 66 | @Override 67 | public final void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 68 | { 69 | if (broken) { 70 | fallbackWriter.serializeAsElement(bean, gen, prov); 71 | return; 72 | } 73 | int value; 74 | try { 75 | value = _propertyAccessor.intField(bean, _propertyIndex); 76 | } catch (Throwable t) { 77 | _handleProblem(bean, gen, prov, t, true); 78 | return; 79 | } 80 | if (!_suppressableIntSet || _suppressableInt != value) { 81 | gen.writeNumber(value); 82 | } else { // important: MUST output a placeholder 83 | serializeAsPlaceholder(bean, gen, prov); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/IntMethodPropertyWriter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.JsonSerializer; 5 | import com.fasterxml.jackson.databind.SerializerProvider; 6 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 7 | 8 | public final class IntMethodPropertyWriter 9 | extends OptimizedBeanPropertyWriter 10 | { 11 | private static final long serialVersionUID = 1L; 12 | 13 | private final int _suppressableInt; 14 | private final boolean _suppressableIntSet; 15 | 16 | public IntMethodPropertyWriter(BeanPropertyWriter src, BeanPropertyAccessor acc, int index, 17 | JsonSerializer ser) { 18 | super(src, acc, index, ser); 19 | 20 | if (_suppressableValue instanceof Integer) { 21 | _suppressableInt = (Integer)_suppressableValue; 22 | _suppressableIntSet = true; 23 | } else { 24 | _suppressableInt = 0; 25 | _suppressableIntSet = false; 26 | } 27 | } 28 | 29 | @Override 30 | public BeanPropertyWriter withSerializer(JsonSerializer ser) { 31 | return new IntMethodPropertyWriter(this, _propertyAccessor, _propertyIndex, ser); 32 | } 33 | 34 | @Override 35 | public IntMethodPropertyWriter withAccessor(BeanPropertyAccessor acc) { 36 | if (acc == null) throw new IllegalArgumentException(); 37 | return new IntMethodPropertyWriter(this, acc, _propertyIndex, _serializer); 38 | } 39 | 40 | /* 41 | /********************************************************** 42 | /* Overrides 43 | /********************************************************** 44 | */ 45 | 46 | @Override 47 | public final void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 48 | { 49 | if (broken) { 50 | fallbackWriter.serializeAsField(bean, gen, prov); 51 | return; 52 | } 53 | int value; 54 | try { 55 | value = _propertyAccessor.intGetter(bean, _propertyIndex); 56 | } catch (Throwable t) { 57 | _handleProblem(bean, gen, prov, t, false); 58 | return; 59 | } 60 | if (!_suppressableIntSet || _suppressableInt != value) { 61 | gen.writeFieldName(_fastName); 62 | gen.writeNumber(value); 63 | } 64 | } 65 | 66 | @Override 67 | public final void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 68 | { 69 | if (broken) { 70 | fallbackWriter.serializeAsElement(bean, gen, prov); 71 | return; 72 | } 73 | int value; 74 | try { 75 | value = _propertyAccessor.intGetter(bean, _propertyIndex); 76 | } catch (Throwable t) { 77 | _handleProblem(bean, gen, prov, t, true); 78 | return; 79 | } 80 | if (!_suppressableIntSet || _suppressableInt != value) { 81 | gen.writeNumber(value); 82 | } else { // important: MUST output a placeholder 83 | serializeAsPlaceholder(bean, gen, prov); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/LongFieldPropertyWriter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.JsonSerializer; 5 | import com.fasterxml.jackson.databind.SerializerProvider; 6 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 7 | 8 | public final class LongFieldPropertyWriter 9 | extends OptimizedBeanPropertyWriter 10 | { 11 | private static final long serialVersionUID = 1L; 12 | 13 | private final long _suppressableLong; 14 | private final boolean _suppressableLongSet; 15 | 16 | public LongFieldPropertyWriter(BeanPropertyWriter src, BeanPropertyAccessor acc, int index, 17 | JsonSerializer ser) { 18 | super(src, acc, index, ser); 19 | 20 | if (_suppressableValue instanceof Long) { 21 | _suppressableLong = (Long)_suppressableValue; 22 | _suppressableLongSet = true; 23 | } else { 24 | _suppressableLong = 0L; 25 | _suppressableLongSet = false; 26 | } 27 | } 28 | 29 | @Override 30 | public BeanPropertyWriter withSerializer(JsonSerializer ser) { 31 | return new LongFieldPropertyWriter(this, _propertyAccessor, _propertyIndex, ser); 32 | } 33 | 34 | @Override 35 | public LongFieldPropertyWriter withAccessor(BeanPropertyAccessor acc) { 36 | if (acc == null) throw new IllegalArgumentException(); 37 | return new LongFieldPropertyWriter(this, acc, _propertyIndex, _serializer); 38 | } 39 | 40 | /* 41 | /********************************************************** 42 | /* Overrides 43 | /********************************************************** 44 | */ 45 | 46 | @Override 47 | public final void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 48 | { 49 | if (broken) { 50 | fallbackWriter.serializeAsField(bean, gen, prov); 51 | return; 52 | } 53 | long value; 54 | try { 55 | value = _propertyAccessor.longField(bean, _propertyIndex); 56 | } catch (Throwable t) { 57 | _handleProblem(bean, gen, prov, t, false); 58 | return; 59 | } 60 | if (!_suppressableLongSet || _suppressableLong != value) { 61 | gen.writeFieldName(_fastName); 62 | gen.writeNumber(value); 63 | } 64 | } 65 | 66 | @Override 67 | public final void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 68 | { 69 | if (broken) { 70 | fallbackWriter.serializeAsElement(bean, gen, prov); 71 | return; 72 | } 73 | long value; 74 | try { 75 | value = _propertyAccessor.longField(bean, _propertyIndex); 76 | } catch (Throwable t) { 77 | _handleProblem(bean, gen, prov, t, false); 78 | return; 79 | } 80 | if (!_suppressableLongSet || _suppressableLong != value) { 81 | gen.writeNumber(value); 82 | } else { // important: MUST output a placeholder 83 | serializeAsPlaceholder(bean, gen, prov); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/LongMethodPropertyWriter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.JsonSerializer; 5 | import com.fasterxml.jackson.databind.SerializerProvider; 6 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 7 | 8 | public final class LongMethodPropertyWriter 9 | extends OptimizedBeanPropertyWriter 10 | { 11 | private static final long serialVersionUID = 1L; 12 | 13 | private final long _suppressableLong; 14 | private final boolean _suppressableLongSet; 15 | 16 | public LongMethodPropertyWriter(BeanPropertyWriter src, BeanPropertyAccessor acc, int index, 17 | JsonSerializer ser) { 18 | super(src, acc, index, ser); 19 | 20 | if (_suppressableValue instanceof Long) { 21 | _suppressableLong = (Long)_suppressableValue; 22 | _suppressableLongSet = true; 23 | } else { 24 | _suppressableLong = 0L; 25 | _suppressableLongSet = false; 26 | } 27 | } 28 | 29 | @Override 30 | public BeanPropertyWriter withSerializer(JsonSerializer ser) { 31 | return new LongMethodPropertyWriter(this, _propertyAccessor, _propertyIndex, ser); 32 | } 33 | 34 | @Override 35 | public LongMethodPropertyWriter withAccessor(BeanPropertyAccessor acc) { 36 | if (acc == null) throw new IllegalArgumentException(); 37 | return new LongMethodPropertyWriter(this, acc, _propertyIndex, _serializer); 38 | } 39 | 40 | /* 41 | /********************************************************** 42 | /* Overrides 43 | /********************************************************** 44 | */ 45 | 46 | @Override 47 | public final void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 48 | { 49 | if (broken) { 50 | fallbackWriter.serializeAsField(bean, gen, prov); 51 | return; 52 | } 53 | long value; 54 | try { 55 | value = _propertyAccessor.longGetter(bean, _propertyIndex); 56 | } catch (Throwable t) { 57 | _handleProblem(bean, gen, prov, t, false); 58 | return; 59 | } 60 | if (!_suppressableLongSet || _suppressableLong != value) { 61 | gen.writeFieldName(_fastName); 62 | gen.writeNumber(value); 63 | } 64 | } 65 | 66 | @Override 67 | public final void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 68 | { 69 | if (broken) { 70 | fallbackWriter.serializeAsElement(bean, gen, prov); 71 | return; 72 | } 73 | long value; 74 | try { 75 | value = _propertyAccessor.longGetter(bean, _propertyIndex); 76 | } catch (Throwable t) { 77 | _handleProblem(bean, gen, prov, t, true); 78 | return; 79 | } 80 | if (!_suppressableLongSet || _suppressableLong != value) { 81 | gen.writeNumber(value); 82 | } else { // important: MUST output a placeholder 83 | serializeAsPlaceholder(bean, gen, prov); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/ObjectFieldPropertyWriter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.JsonSerializer; 5 | import com.fasterxml.jackson.databind.SerializerProvider; 6 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 7 | import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; 8 | 9 | public class ObjectFieldPropertyWriter 10 | extends OptimizedBeanPropertyWriter 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public ObjectFieldPropertyWriter(BeanPropertyWriter src, BeanPropertyAccessor acc, int index, 15 | JsonSerializer ser) { 16 | super(src, acc, index, ser); 17 | } 18 | 19 | @Override 20 | public BeanPropertyWriter withSerializer(JsonSerializer ser) { 21 | return new ObjectFieldPropertyWriter(this, _propertyAccessor, _propertyIndex, ser); 22 | } 23 | 24 | @Override 25 | public ObjectFieldPropertyWriter withAccessor(BeanPropertyAccessor acc) { 26 | if (acc == null) throw new IllegalArgumentException(); 27 | return new ObjectFieldPropertyWriter(this, acc, _propertyIndex, _serializer); 28 | } 29 | 30 | /* 31 | /********************************************************** 32 | /* Overrides 33 | /********************************************************** 34 | */ 35 | 36 | @Override 37 | public final void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 38 | { 39 | if (broken) { 40 | fallbackWriter.serializeAsField(bean, gen, prov); 41 | return; 42 | } 43 | Object value; 44 | try { 45 | value = _propertyAccessor.objectField(bean, _propertyIndex); 46 | } catch (Throwable t) { 47 | _handleProblem(bean, gen, prov, t, false); 48 | return; 49 | } 50 | // Null (etc) handling; copied from super-class impl 51 | if (value == null) { 52 | if (_nullSerializer != null) { 53 | gen.writeFieldName(_fastName); 54 | _nullSerializer.serialize(null, gen, prov); 55 | } else if (!_suppressNulls) { 56 | gen.writeFieldName(_fastName); 57 | prov.defaultSerializeNull(gen); 58 | } 59 | return; 60 | } 61 | JsonSerializer ser = _serializer; 62 | if (ser == null) { 63 | Class cls = value.getClass(); 64 | PropertySerializerMap map = _dynamicSerializers; 65 | ser = map.serializerFor(cls); 66 | if (ser == null) { 67 | ser = _findAndAddDynamic(map, cls, prov); 68 | } 69 | } 70 | if (_suppressableValue != null) { 71 | if (MARKER_FOR_EMPTY == _suppressableValue) { 72 | if (ser.isEmpty(prov, value)) { 73 | return; 74 | } 75 | } else if (_suppressableValue.equals(value)) { 76 | return; 77 | } 78 | } 79 | if (value == bean) { 80 | // three choices: exception; handled by call; or pass-through 81 | if (_handleSelfReference(bean, gen, prov, ser)) { 82 | return; 83 | } 84 | } 85 | gen.writeFieldName(_fastName); 86 | if (_typeSerializer == null) { 87 | ser.serialize(value, gen, prov); 88 | } else { 89 | ser.serializeWithType(value, gen, prov, _typeSerializer); 90 | } 91 | } 92 | 93 | @Override 94 | public final void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 95 | { 96 | if (broken) { 97 | fallbackWriter.serializeAsElement(bean, gen, prov); 98 | return; 99 | } 100 | Object value; 101 | try { 102 | value = _propertyAccessor.objectField(bean, _propertyIndex); 103 | } catch (Throwable t) { 104 | _handleProblem(bean, gen, prov, t, true); 105 | return; 106 | } 107 | if (value == null) { 108 | if (_nullSerializer != null) { 109 | _nullSerializer.serialize(null, gen, prov); 110 | } else if (_suppressNulls) { 111 | serializeAsPlaceholder(bean, gen, prov); 112 | } else { 113 | prov.defaultSerializeNull(gen); 114 | } 115 | return; 116 | } 117 | JsonSerializer ser = _serializer; 118 | if (ser == null) { 119 | Class cls = value.getClass(); 120 | PropertySerializerMap map = _dynamicSerializers; 121 | ser = map.serializerFor(cls); 122 | if (ser == null) { 123 | ser = _findAndAddDynamic(map, cls, prov); 124 | } 125 | } 126 | if (_suppressableValue != null) { 127 | if (MARKER_FOR_EMPTY == _suppressableValue) { 128 | if (ser.isEmpty(prov, value)) { 129 | serializeAsPlaceholder(bean, gen, prov); 130 | return; 131 | } 132 | } else if (_suppressableValue.equals(value)) { 133 | serializeAsPlaceholder(bean, gen, prov); 134 | return; 135 | } 136 | } 137 | if (value == bean) { 138 | // three choices: exception; handled by call; or pass-through 139 | if (_handleSelfReference(bean, gen, prov, ser)) { 140 | return; 141 | } 142 | } 143 | if (_typeSerializer == null) { 144 | ser.serialize(value, gen, prov); 145 | } else { 146 | ser.serializeWithType(value, gen, prov, _typeSerializer); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/ObjectMethodPropertyWriter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.JsonSerializer; 5 | import com.fasterxml.jackson.databind.SerializerProvider; 6 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 7 | import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; 8 | 9 | public class ObjectMethodPropertyWriter 10 | extends OptimizedBeanPropertyWriter 11 | { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public ObjectMethodPropertyWriter(BeanPropertyWriter src, BeanPropertyAccessor acc, int index, 15 | JsonSerializer ser) { 16 | super(src, acc, index, ser); 17 | } 18 | 19 | @Override 20 | public BeanPropertyWriter withSerializer(JsonSerializer ser) { 21 | return new ObjectMethodPropertyWriter(this, _propertyAccessor, _propertyIndex, ser); 22 | } 23 | 24 | @Override 25 | public ObjectMethodPropertyWriter withAccessor(BeanPropertyAccessor acc) { 26 | if (acc == null) throw new IllegalArgumentException(); 27 | return new ObjectMethodPropertyWriter(this, acc, _propertyIndex, _serializer); 28 | } 29 | 30 | /* 31 | /********************************************************** 32 | /* Overrides 33 | /********************************************************** 34 | */ 35 | 36 | @Override 37 | public final void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 38 | { 39 | if (broken) { 40 | fallbackWriter.serializeAsField(bean, gen, prov); 41 | return; 42 | } 43 | Object value; 44 | try { 45 | value = _propertyAccessor.objectGetter(bean, _propertyIndex); 46 | } catch (Throwable t) { 47 | _handleProblem(bean, gen, prov, t, false); 48 | return; 49 | } 50 | // Null (etc) handling; copied from super-class impl 51 | if (value == null) { 52 | if (_nullSerializer != null) { 53 | gen.writeFieldName(_fastName); 54 | _nullSerializer.serialize(null, gen, prov); 55 | } else if (!_suppressNulls) { 56 | gen.writeFieldName(_fastName); 57 | prov.defaultSerializeNull(gen); 58 | } 59 | return; 60 | } 61 | JsonSerializer ser = _serializer; 62 | if (ser == null) { 63 | Class cls = value.getClass(); 64 | PropertySerializerMap map = _dynamicSerializers; 65 | ser = map.serializerFor(cls); 66 | if (ser == null) { 67 | ser = _findAndAddDynamic(map, cls, prov); 68 | } 69 | } 70 | if (_suppressableValue != null) { 71 | if (MARKER_FOR_EMPTY == _suppressableValue) { 72 | if (ser.isEmpty(prov, value)) { 73 | return; 74 | } 75 | } else if (_suppressableValue.equals(value)) { 76 | return; 77 | } 78 | } 79 | if (value == bean) { 80 | // three choices: exception; handled by call; or pass-through 81 | if (_handleSelfReference(bean, gen, prov, ser)) { 82 | return; 83 | } 84 | } 85 | gen.writeFieldName(_fastName); 86 | if (_typeSerializer == null) { 87 | ser.serialize(value, gen, prov); 88 | } else { 89 | ser.serializeWithType(value, gen, prov, _typeSerializer); 90 | } 91 | } 92 | 93 | @Override 94 | public final void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 95 | { 96 | if (broken) { 97 | fallbackWriter.serializeAsElement(bean, gen, prov); 98 | return; 99 | } 100 | Object value; 101 | try { 102 | value = _propertyAccessor.objectGetter(bean, _propertyIndex); 103 | } catch (Throwable t) { 104 | _handleProblem(bean, gen, prov, t, true); 105 | return; 106 | } 107 | // Null (etc) handling; copied from super-class impl 108 | if (value == null) { 109 | if (_nullSerializer != null) { 110 | _nullSerializer.serialize(null, gen, prov); 111 | } else if (_suppressNulls) { 112 | serializeAsPlaceholder(bean, gen, prov); 113 | } else { 114 | prov.defaultSerializeNull(gen); 115 | } 116 | return; 117 | } 118 | JsonSerializer ser = _serializer; 119 | if (ser == null) { 120 | Class cls = value.getClass(); 121 | PropertySerializerMap map = _dynamicSerializers; 122 | ser = map.serializerFor(cls); 123 | if (ser == null) { 124 | ser = _findAndAddDynamic(map, cls, prov); 125 | } 126 | } 127 | if (_suppressableValue != null) { 128 | if (MARKER_FOR_EMPTY == _suppressableValue) { 129 | if (ser.isEmpty(prov, value)) { 130 | serializeAsPlaceholder(bean, gen, prov); 131 | return; 132 | } 133 | } else if (_suppressableValue.equals(value)) { 134 | serializeAsPlaceholder(bean, gen, prov); 135 | return; 136 | } 137 | } 138 | if (value == bean) { 139 | // three choices: exception; handled by call; or pass-through 140 | if (_handleSelfReference(bean, gen, prov, ser)) { 141 | return; 142 | } 143 | } 144 | if (_typeSerializer == null) { 145 | ser.serialize(value, gen, prov); 146 | } else { 147 | ser.serializeWithType(value, gen, prov, _typeSerializer); 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/OptimizedBeanPropertyWriter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import java.util.logging.Level; 4 | import java.util.logging.Logger; 5 | 6 | import com.fasterxml.jackson.core.JsonGenerator; 7 | import com.fasterxml.jackson.core.SerializableString; 8 | 9 | import com.fasterxml.jackson.databind.*; 10 | import com.fasterxml.jackson.databind.jsontype.TypeSerializer; 11 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 12 | import com.fasterxml.jackson.databind.util.ClassUtil; 13 | 14 | /** 15 | * Intermediate base class that is used for concrete 16 | * per-type implementations 17 | */ 18 | @SuppressWarnings("serial") 19 | abstract class OptimizedBeanPropertyWriter> 20 | extends BeanPropertyWriter 21 | { 22 | protected final BeanPropertyAccessor _propertyAccessor; 23 | 24 | /** 25 | * Locally stored version of efficiently serializable name. 26 | * Used to work around earlier problems with typing between 27 | * interface, implementation 28 | * 29 | * @since 2.5 30 | */ 31 | protected final SerializableString _fastName; 32 | protected final int _propertyIndex; 33 | 34 | protected final BeanPropertyWriter fallbackWriter; 35 | // Not volatile to prevent overhead, worst case is we trip the exception a few extra times 36 | protected boolean broken = false; 37 | 38 | protected OptimizedBeanPropertyWriter(BeanPropertyWriter src, 39 | BeanPropertyAccessor propertyAccessor, int propertyIndex, 40 | JsonSerializer ser) 41 | { 42 | super(src); 43 | this.fallbackWriter = unwrapFallbackWriter(src); 44 | // either use the passed on serializer or the original one 45 | _serializer = (ser != null) ? ser : src.getSerializer(); 46 | _propertyAccessor = propertyAccessor; 47 | _propertyIndex = propertyIndex; 48 | _fastName = src.getSerializedName(); 49 | } 50 | 51 | private BeanPropertyWriter unwrapFallbackWriter(BeanPropertyWriter srcIn) 52 | { 53 | while (srcIn instanceof OptimizedBeanPropertyWriter) { 54 | srcIn = ((OptimizedBeanPropertyWriter)srcIn).fallbackWriter; 55 | } 56 | return srcIn; 57 | } 58 | 59 | // Overridden since 2.6.3 60 | @Override 61 | public void assignTypeSerializer(TypeSerializer typeSer) { 62 | super.assignTypeSerializer(typeSer); 63 | if (fallbackWriter != null) { 64 | fallbackWriter.assignTypeSerializer(typeSer); 65 | } 66 | // 04-Oct-2015, tatu: Should we handle this wrt [module-afterburner#59]? 67 | // Seems unlikely, as String/long/int/boolean are final types; and for 68 | // basic 'Object' we delegate to deserializer as expected 69 | } 70 | 71 | // Overridden since 2.6.3 72 | @Override 73 | public void assignSerializer(JsonSerializer ser) { 74 | super.assignSerializer(ser); 75 | if (fallbackWriter != null) { 76 | fallbackWriter.assignSerializer(ser); 77 | } 78 | // 04-Oct-2015, tatu: To fix [module-afterburner#59], need to disable use of 79 | // fully optimized variant 80 | if (!isDefaultSerializer(ser)) { 81 | broken = true; 82 | } 83 | } 84 | 85 | @Override // since 2.7.6 86 | public void assignNullSerializer(JsonSerializer nullSer) { 87 | super.assignNullSerializer(nullSer); 88 | if (fallbackWriter != null) { 89 | fallbackWriter.assignNullSerializer(nullSer); 90 | } 91 | } 92 | 93 | public abstract T withAccessor(BeanPropertyAccessor acc); 94 | 95 | public abstract BeanPropertyWriter withSerializer(JsonSerializer ser); 96 | 97 | @Override 98 | public abstract void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) throws Exception; 99 | 100 | // since 2.4.3 101 | @Override 102 | public abstract void serializeAsElement(Object bean, JsonGenerator jgen, SerializerProvider prov) throws Exception; 103 | 104 | // note: synchronized used to try to minimize race conditions; also, should NOT 105 | // be a performance problem 106 | protected synchronized void _handleProblem(Object bean, JsonGenerator gen, SerializerProvider prov, 107 | Throwable t, boolean element) throws Exception 108 | { 109 | if ((t instanceof IllegalAccessError) 110 | || (t instanceof SecurityException)) { 111 | _reportProblem(bean, t); 112 | if (element) { 113 | fallbackWriter.serializeAsElement(bean, gen, prov); 114 | } else { 115 | fallbackWriter.serializeAsField(bean, gen, prov); 116 | } 117 | return; 118 | } 119 | if (t instanceof Error) { 120 | throw (Error) t; 121 | } 122 | throw (Exception) t; 123 | } 124 | 125 | protected void _reportProblem(Object bean, Throwable e) 126 | { 127 | broken = true; 128 | String msg = String.format("Disabling Afterburner serialization for %s (field #%d; muator %s), due to access error (type %s, message=%s)%n", 129 | bean.getClass(), _propertyIndex, getClass().getName(), 130 | e.getClass().getName(), e.getMessage()); 131 | Logger.getLogger(OptimizedBeanPropertyWriter.class.getName()).log(Level.WARNING, msg, e); 132 | } 133 | 134 | /** 135 | * Helper method used to check whether given serializer is the default 136 | * serializer implementation: this is necessary to avoid overriding other 137 | * kinds of deserializers. 138 | */ 139 | protected boolean isDefaultSerializer(JsonSerializer ser) 140 | { 141 | return (ser == null) || ClassUtil.isJacksonStdImpl(ser); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/StringFieldPropertyWriter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.JsonSerializer; 5 | import com.fasterxml.jackson.databind.SerializerProvider; 6 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 7 | 8 | public final class StringFieldPropertyWriter 9 | extends OptimizedBeanPropertyWriter 10 | { 11 | private static final long serialVersionUID = 1L; 12 | 13 | public StringFieldPropertyWriter(BeanPropertyWriter src, BeanPropertyAccessor acc, int index, 14 | JsonSerializer ser) { 15 | super(src, acc, index, ser); 16 | } 17 | 18 | @Override 19 | public BeanPropertyWriter withSerializer(JsonSerializer ser) { 20 | return new StringFieldPropertyWriter(this, _propertyAccessor, _propertyIndex, ser); 21 | } 22 | 23 | @Override 24 | public StringFieldPropertyWriter withAccessor(BeanPropertyAccessor acc) { 25 | if (acc == null) throw new IllegalArgumentException(); 26 | return new StringFieldPropertyWriter(this, acc, _propertyIndex, _serializer); 27 | } 28 | 29 | /* 30 | /********************************************************** 31 | /* Overrides 32 | /********************************************************** 33 | */ 34 | 35 | @Override 36 | public final void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 37 | { 38 | if (broken) { 39 | fallbackWriter.serializeAsField(bean, gen, prov); 40 | return; 41 | } 42 | String value; 43 | try { 44 | value = _propertyAccessor.stringField(bean, _propertyIndex); 45 | } catch (Throwable t) { 46 | _handleProblem(bean, gen, prov, t, false); 47 | return; 48 | } 49 | // Null (etc) handling; copied from super-class impl 50 | if (value == null) { 51 | if (!_suppressNulls) { 52 | gen.writeFieldName(_fastName); 53 | prov.defaultSerializeNull(gen); 54 | } 55 | return; 56 | } 57 | if (_suppressableValue != null) { 58 | if (MARKER_FOR_EMPTY == _suppressableValue) { 59 | if (value.length() == 0) { 60 | return; 61 | } 62 | } else if (_suppressableValue.equals(value)) { 63 | return; 64 | } 65 | } 66 | gen.writeFieldName(_fastName); 67 | gen.writeString(value); 68 | } 69 | 70 | @Override 71 | public final void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 72 | { 73 | if (broken) { 74 | fallbackWriter.serializeAsElement(bean, gen, prov); 75 | return; 76 | } 77 | String value; 78 | try { 79 | value = _propertyAccessor.stringField(bean, _propertyIndex); 80 | } catch (Throwable t) { 81 | _handleProblem(bean, gen, prov, t, true); 82 | return; 83 | } 84 | if (_suppressableValue != null) { 85 | if (MARKER_FOR_EMPTY == _suppressableValue) { 86 | if (value.length() == 0) { 87 | serializeAsPlaceholder(bean, gen, prov); 88 | return; 89 | } 90 | } else if (_suppressableValue.equals(value)) { 91 | serializeAsPlaceholder(bean, gen, prov); 92 | return; 93 | } 94 | } 95 | gen.writeString(value); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/ser/StringMethodPropertyWriter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.JsonSerializer; 5 | import com.fasterxml.jackson.databind.SerializerProvider; 6 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 7 | 8 | public class StringMethodPropertyWriter 9 | extends OptimizedBeanPropertyWriter 10 | { 11 | private static final long serialVersionUID = 1L; 12 | 13 | public StringMethodPropertyWriter(BeanPropertyWriter src, BeanPropertyAccessor acc, int index, 14 | JsonSerializer ser) { 15 | super(src, acc, index, ser); 16 | } 17 | 18 | @Override 19 | public BeanPropertyWriter withSerializer(JsonSerializer ser) { 20 | return new StringMethodPropertyWriter(this, _propertyAccessor, _propertyIndex, ser); 21 | } 22 | 23 | @Override 24 | public StringMethodPropertyWriter withAccessor(BeanPropertyAccessor acc) { 25 | if (acc == null) throw new IllegalArgumentException(); 26 | return new StringMethodPropertyWriter(this, acc, _propertyIndex, _serializer); 27 | } 28 | 29 | /* 30 | /********************************************************** 31 | /* Overrides 32 | /********************************************************** 33 | */ 34 | 35 | @Override 36 | public final void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 37 | { 38 | if (broken) { 39 | fallbackWriter.serializeAsField(bean, gen, prov); 40 | return; 41 | } 42 | String value; 43 | try { 44 | value = _propertyAccessor.stringGetter(bean, _propertyIndex); 45 | } catch (Throwable t) { 46 | _handleProblem(bean, gen, prov, t, false); 47 | return; 48 | } 49 | // Null (etc) handling; copied from super-class impl 50 | if (value == null) { 51 | if (!_suppressNulls) { 52 | gen.writeFieldName(_fastName); 53 | prov.defaultSerializeNull(gen); 54 | } 55 | return; 56 | } 57 | if (_suppressableValue != null) { 58 | if (MARKER_FOR_EMPTY == _suppressableValue) { 59 | if (value.length() == 0) { 60 | return; 61 | } 62 | } else if (_suppressableValue.equals(value)) { 63 | return; 64 | } 65 | } 66 | gen.writeFieldName(_fastName); 67 | gen.writeString(value); 68 | } 69 | 70 | @Override 71 | public final void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception 72 | { 73 | if (broken) { 74 | fallbackWriter.serializeAsElement(bean, gen, prov); 75 | return; 76 | } 77 | 78 | String value; 79 | try { 80 | value = _propertyAccessor.stringGetter(bean, _propertyIndex); 81 | } catch (Throwable t) { 82 | _handleProblem(bean, gen, prov, t, true); 83 | return; 84 | } 85 | // Null (etc) handling; copied from super-class impl 86 | if (value == null) { 87 | if (_suppressNulls) { 88 | serializeAsPlaceholder(bean, gen, prov); 89 | } else { 90 | prov.defaultSerializeNull(gen); 91 | } 92 | return; 93 | } 94 | if (_suppressableValue != null) { 95 | if (MARKER_FOR_EMPTY == _suppressableValue) { 96 | if (value.length() == 0) { 97 | serializeAsPlaceholder(bean, gen, prov); 98 | return; 99 | } 100 | } else if (_suppressableValue.equals(value)) { 101 | serializeAsPlaceholder(bean, gen, prov); 102 | return; 103 | } 104 | } 105 | gen.writeString(value); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/util/ClassName.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.util; 2 | 3 | import java.util.zip.Adler32; 4 | 5 | /** 6 | * Accessing various permutations of dotted/slashed representations gets 7 | * tiresome after a while, so here's an abstraction for hiding complexities, 8 | * and for performing lazy transformations as necessary. 9 | */ 10 | public class ClassName 11 | { 12 | public final static String TEMPLATE_SUFFIX = actualClassName("", 0L); 13 | 14 | // Basenames with no checksum suffix 15 | protected final String _dottedBase; 16 | 17 | protected String _slashedBase; 18 | 19 | protected String _dottedName, _slashedName; 20 | 21 | protected long _checksum; 22 | 23 | private ClassName(String dottedBase) { 24 | _dottedBase = dottedBase; 25 | } 26 | 27 | public static ClassName constructFor(Class baseClass, String suffix) { 28 | return new ClassName(baseClass.getName() + suffix); 29 | } 30 | 31 | public void assignChecksum(byte[] data) { 32 | long l = adler32(data); 33 | if (_checksum != 0L) { 34 | throw new IllegalStateException("Trying to re-assign checksum as 0x"+Long.toHexString(l) 35 | +" (had 0x"+Long.toHexString(_checksum)+")"); 36 | } 37 | // Need to mask unlikely checksum of 0 38 | if (l == 0L) { 39 | l = 1; 40 | } 41 | _checksum = l; 42 | } 43 | 44 | public String getDottedTemplate() { 45 | return _dottedBase + TEMPLATE_SUFFIX; 46 | } 47 | 48 | public String getSlashedTemplate() { 49 | return getSlashedBase() + TEMPLATE_SUFFIX; 50 | } 51 | 52 | public String getDottedName() { 53 | if (_dottedName == null) { 54 | if (_checksum == 0) { 55 | throw new IllegalStateException("No checksum assigned yet"); 56 | } 57 | _dottedName = String.format("%s%08x", getDottedBase(), (int) _checksum); 58 | } 59 | return _dottedName; 60 | } 61 | 62 | public String getSlashedName() { 63 | if (_slashedName == null) { 64 | if (_checksum == 0) { 65 | throw new IllegalStateException("No checksum assigned yet"); 66 | } 67 | _slashedName = String.format("%s%08x", getSlashedBase(), (int) _checksum); 68 | } 69 | return _slashedName; 70 | } 71 | 72 | public String getSourceFilename() { 73 | return getSlashedBase() + ".java"; 74 | } 75 | 76 | public String getDottedBase() { 77 | return _dottedBase; 78 | } 79 | 80 | public String getSlashedBase() { 81 | if (_slashedBase == null) { 82 | _slashedBase = dotsToSlashes(_dottedBase); 83 | } 84 | return _slashedBase; 85 | } 86 | 87 | @Override 88 | public String toString() { 89 | return getDottedName(); 90 | } 91 | 92 | private static String actualClassName(String base, long checksum) { 93 | return String.format("%s%08x", base, (int) checksum); 94 | } 95 | 96 | protected static String dotsToSlashes(String className) { 97 | return className.replace(".", "/"); 98 | } 99 | 100 | protected static long adler32(byte[] data) 101 | { 102 | Adler32 adler = new Adler32(); 103 | adler.update(data); 104 | return adler.getValue(); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/util/DynamicPropertyAccessorBase.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.util; 2 | 3 | 4 | import java.util.List; 5 | 6 | import org.objectweb.asm.MethodVisitor; 7 | 8 | import static org.objectweb.asm.Opcodes.*; 9 | 10 | public class DynamicPropertyAccessorBase 11 | { 12 | protected final static int[] ALL_INT_CONSTS = new int[] { 13 | ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4 14 | }; 15 | 16 | protected int _accessorCount = 0; 17 | 18 | protected DynamicPropertyAccessorBase() { 19 | } 20 | 21 | public final boolean isEmpty() { 22 | return (_accessorCount == 0); 23 | } 24 | 25 | /* 26 | /********************************************************** 27 | /* Helper methods, generating common pieces 28 | /********************************************************** 29 | */ 30 | 31 | protected static void generateException(MethodVisitor mv, String beanClass, int propertyCount) 32 | { 33 | mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException"); 34 | mv.visitInsn(DUP); 35 | mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); 36 | mv.visitInsn(DUP); 37 | mv.visitLdcInsn("Invalid field index (valid; 0 <= n < "+propertyCount+"): "); 38 | mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "(Ljava/lang/String;)V", false); 39 | mv.visitVarInsn(ILOAD, 2); 40 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;", false); 41 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); 42 | mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "", "(Ljava/lang/String;)V", false); 43 | mv.visitInsn(ATHROW); 44 | } 45 | 46 | /* 47 | /********************************************************** 48 | /* Helper methods, other 49 | /********************************************************** 50 | */ 51 | 52 | protected static String internalClassName(String className) { 53 | return className.replace(".", "/"); 54 | } 55 | 56 | protected T _add(List list, T value) { 57 | list.add(value); 58 | ++_accessorCount; 59 | return value; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/fasterxml/jackson/module/afterburner/util/MyClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.util; 2 | 3 | import java.lang.reflect.Method; 4 | import java.nio.charset.Charset; 5 | 6 | /** 7 | * Class loader that is needed to load generated classes. 8 | */ 9 | public class MyClassLoader extends ClassLoader 10 | { 11 | private final static Charset UTF8 = Charset.forName("UTF-8"); 12 | 13 | /** 14 | * Flag that determines if we should first try to load new class 15 | * using parent class loader or not; this may be done to try to 16 | * force access to protected/package-access properties. 17 | */ 18 | protected final boolean _cfgUseParentLoader; 19 | 20 | public MyClassLoader(ClassLoader parent, boolean tryToUseParent) 21 | { 22 | super(parent); 23 | _cfgUseParentLoader = tryToUseParent; 24 | } 25 | 26 | /** 27 | * Helper method called to check whether it is acceptable to create a new 28 | * class in package that given class is part of. 29 | * This is used to prevent certain class of failures, related to access 30 | * limitations: for example, we can not add classes in sealed packages, 31 | * or core Java packages (java.*). 32 | * 33 | * @since 2.2.1 34 | */ 35 | public static boolean canAddClassInPackageOf(Class cls) 36 | { 37 | final Package beanPackage = cls.getPackage(); 38 | if (beanPackage != null) { 39 | if (beanPackage.isSealed()) { 40 | return false; 41 | } 42 | String pname = beanPackage.getName(); 43 | /* 14-Aug-2014, tatu: java.* we do not want to touch, but 44 | * javax is bit trickier. For now let's 45 | */ 46 | if (pname.startsWith("java.") 47 | || pname.startsWith("javax.security.")) { 48 | return false; 49 | } 50 | } 51 | return true; 52 | } 53 | 54 | /** 55 | * @param className Interface or abstract class that class to load should extend or 56 | * implement 57 | */ 58 | public Class loadAndResolve(ClassName className, byte[] byteCode) 59 | throws IllegalArgumentException 60 | { 61 | // First things first: just to be sure; maybe we have already loaded it? 62 | Class old = findLoadedClass(className.getDottedName()); 63 | if (old != null) { 64 | return old; 65 | } 66 | 67 | Class impl; 68 | 69 | // Important: bytecode is generated with a template name (since bytecode itself 70 | // is used for checksum calculation) -- must be replaced now, however 71 | replaceName(byteCode, className.getSlashedTemplate(), className.getSlashedName()); 72 | 73 | // First: let's try calling it directly on parent, to be able to access protected/package-access stuff: 74 | if (_cfgUseParentLoader) { 75 | ClassLoader cl = getParent(); 76 | // if we have parent, that is 77 | if (cl != null) { 78 | try { 79 | Method method = ClassLoader.class.getDeclaredMethod("defineClass", 80 | new Class[] {String.class, byte[].class, int.class, 81 | int.class}); 82 | method.setAccessible(true); 83 | return (Class)method.invoke(getParent(), 84 | className.getDottedName(), byteCode, 0, byteCode.length); 85 | } catch (Exception e) { 86 | // Should we handle this somehow? 87 | } 88 | } 89 | } 90 | 91 | // but if that doesn't fly, try to do it from our own class loader 92 | 93 | try { 94 | impl = defineClass(className.getDottedName(), byteCode, 0, byteCode.length); 95 | } catch (LinkageError e) { 96 | Throwable t = e; 97 | while (t.getCause() != null) { 98 | t = t.getCause(); 99 | } 100 | throw new IllegalArgumentException("Failed to load class '"+className+"': "+t.getMessage(), t); 101 | } 102 | // important: must also resolve the class... 103 | resolveClass(impl); 104 | return impl; 105 | } 106 | 107 | public static int replaceName(byte[] byteCode, 108 | String from, String to) 109 | { 110 | byte[] fromB = from.getBytes(UTF8); 111 | byte[] toB = to.getBytes(UTF8); 112 | 113 | final int matchLength = fromB.length; 114 | 115 | // sanity check 116 | if (matchLength != toB.length) { 117 | throw new IllegalArgumentException("From String '"+from 118 | +"' has different length than To String '"+to+"'"); 119 | } 120 | 121 | int i = 0; 122 | int count = 0; 123 | 124 | // naive; for now has to do 125 | main_loop: 126 | for (int end = byteCode.length - matchLength; i <= end; ) { 127 | if (byteCode[i++] == fromB[0]) { 128 | for (int j = 1; j < matchLength; ++j) { 129 | if (fromB[j] != byteCode[i+j-1]) { 130 | continue main_loop; 131 | } 132 | } 133 | ++count; 134 | System.arraycopy(toB, 0, byteCode, i-1, matchLength); 135 | i += (matchLength-1); 136 | } 137 | } 138 | return count; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/LICENSE: -------------------------------------------------------------------------------- 1 | This copy of Jackson JSON processor databind module is licensed under the 2 | Apache (Software) License, version 2.0 ("the License"). 3 | See the License for details about distribution rights, and the 4 | specific rights regarding derivate works. 5 | 6 | You may obtain a copy of the License at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module: -------------------------------------------------------------------------------- 1 | com.fasterxml.jackson.module.afterburner.AfterburnerModule 2 | 3 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/TestAccessFallback.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | 5 | public class TestAccessFallback extends AfterburnerTestBase 6 | { 7 | @SuppressWarnings("serial") 8 | static class BogusTestError extends IllegalAccessError { 9 | public BogusTestError(String msg) { 10 | super(msg); 11 | } 12 | } 13 | 14 | static class MyBean 15 | { 16 | private String e; 17 | 18 | public MyBean() { } 19 | 20 | MyBean(String e) 21 | { 22 | setE(e); 23 | } 24 | 25 | public void setE(String e) 26 | { 27 | /* 07-Mar-2015, tatu: This is bit tricky, as the exact stack trace varies 28 | * depending on how code is generated. So right now we must get the call 29 | * immediately from constructed class. 30 | */ 31 | 32 | StackTraceElement[] elems = new Throwable().getStackTrace(); 33 | StackTraceElement prev = elems[1]; 34 | if (prev.getClassName().contains("Access4JacksonDeserializer")) { 35 | throw new BogusTestError("boom!"); 36 | } 37 | this.e = e; 38 | } 39 | 40 | public String getE() 41 | { 42 | for (StackTraceElement elem : new Throwable().getStackTrace()) { 43 | if (elem.getClassName().contains("Access4JacksonSerializer")) { 44 | throw new BogusTestError("boom!"); 45 | } 46 | } 47 | return e; 48 | } 49 | } 50 | 51 | private static final String BEAN_JSON = "{\"e\":\"a\"}"; 52 | 53 | public void testSerializeAccess() throws Exception 54 | { 55 | ObjectMapper abMapper = mapperWithModule(); 56 | assertEquals(BEAN_JSON, abMapper.writeValueAsString(new MyBean("a"))); 57 | } 58 | 59 | public void testDeserializeAccess() throws Exception 60 | { 61 | ObjectMapper abMapper = mapperWithModule(); 62 | MyBean bean = abMapper.readValue(BEAN_JSON, MyBean.class); 63 | assertEquals("a", bean.getE()); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/TestSealedPackages.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | 5 | /** 6 | * Tests for [Issue#21] 7 | */ 8 | public class TestSealedPackages extends AfterburnerTestBase 9 | { 10 | public void testJavaStdDeserialization() throws Exception 11 | { 12 | final ObjectMapper MAPPER = mapperWithModule(); 13 | String json = "{}"; 14 | Exception e = MAPPER.readValue(json, Exception.class); 15 | assertNotNull(e); 16 | } 17 | 18 | public void testJavaStdSerialization() throws Exception 19 | { 20 | final ObjectMapper MAPPER = mapperWithModule(); 21 | String json = MAPPER.writeValueAsString(Thread.currentThread().getThreadGroup()); 22 | assertNotNull(json); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/TestUnwrapped.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner; 2 | 3 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 4 | import com.fasterxml.jackson.annotation.JsonUnwrapped; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | 7 | public class TestUnwrapped extends AfterburnerTestBase 8 | { 9 | @JsonPropertyOrder({ "a", "b" }) 10 | static class Wrapper 11 | { 12 | public int a; 13 | 14 | @JsonUnwrapped(prefix="foo.") 15 | public Unwrapped b; 16 | 17 | public Wrapper() { } 18 | public Wrapper(int a, int value) { 19 | this.a = a; 20 | b = new Unwrapped(value); 21 | } 22 | } 23 | 24 | static class Unwrapped { 25 | public int value; 26 | 27 | public Unwrapped() { } 28 | public Unwrapped(int v) { value = v; } 29 | } 30 | 31 | /* 32 | /********************************************************** 33 | /* Actual tests 34 | /********************************************************** 35 | */ 36 | 37 | public void testSimpleSerialize() throws Exception 38 | { 39 | final ObjectMapper VANILLA = new ObjectMapper(); 40 | final ObjectMapper BURNER = mapperWithModule(); 41 | Wrapper input = new Wrapper(1, 3); 42 | String json = VANILLA.writeValueAsString(input); 43 | assertEquals(json, BURNER.writeValueAsString(input)); 44 | } 45 | 46 | public void testUnwrappedDeserialize() throws Exception 47 | { 48 | final ObjectMapper VANILLA = new ObjectMapper(); 49 | final ObjectMapper BURNER = mapperWithModule(); 50 | String json = VANILLA.writeValueAsString(new Wrapper(2, 9)); 51 | Wrapper out = BURNER.readValue(json, Wrapper.class); 52 | assertEquals(2, out.a); 53 | assertNotNull(out.b); 54 | assertEquals(9, out.b.value); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/TestVersions.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner; 2 | 3 | import java.io.*; 4 | 5 | import com.fasterxml.jackson.core.Version; 6 | import com.fasterxml.jackson.core.Versioned; 7 | 8 | /** 9 | * Tests to verify that version information is properly accessible 10 | */ 11 | public class TestVersions extends AfterburnerTestBase 12 | { 13 | public void testMapperVersions() throws IOException 14 | { 15 | AfterburnerModule module = new AfterburnerModule(); 16 | assertVersion(module); 17 | } 18 | 19 | /* 20 | /********************************************************** 21 | /* Helper methods 22 | /********************************************************** 23 | */ 24 | 25 | private void assertVersion(Versioned vers) 26 | { 27 | Version v = vers.version(); 28 | assertFalse("Should find version information (got "+v+")", v.isUnknownVersion()); 29 | Version exp = PackageVersion.VERSION; 30 | assertEquals(exp.toFullString(), v.toFullString()); 31 | assertEquals(exp, v); 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/codegen/GenerateWithMixinsTest.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.codegen; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 7 | 8 | // for [afterburner#51], where re-generation of classes does not work 9 | // as expected 10 | public class GenerateWithMixinsTest extends AfterburnerTestBase 11 | { 12 | static class SampleObject { 13 | private String field1; 14 | private int field2; 15 | private byte[] field3; 16 | 17 | public SampleObject(String field1, int field2, byte[] field3) { 18 | this.field1 = field1; 19 | this.field2 = field2; 20 | this.field3 = field3; 21 | } 22 | 23 | public String getField1() { 24 | return field1; 25 | } 26 | 27 | public void setField1(String field1) { 28 | this.field1 = field1; 29 | } 30 | 31 | public int getField2() { 32 | return field2; 33 | } 34 | 35 | public void setField2(int field2) { 36 | this.field2 = field2; 37 | } 38 | 39 | public byte[] getField3() { 40 | return field3; 41 | } 42 | 43 | public void setField3(byte[] field3) { 44 | this.field3 = field3; 45 | } 46 | } 47 | 48 | public abstract class IgnoreField3MixIn { 49 | @JsonIgnore 50 | public abstract byte[] getField3(); 51 | } 52 | 53 | public void testIssue51() throws JsonProcessingException 54 | { 55 | SampleObject sampleObject = new SampleObject("field1", 2, "field3".getBytes()); 56 | 57 | ObjectMapper objectMapper = mapperWithModule(); 58 | 59 | ObjectMapper objectMapperCopy = objectMapper.copy(); 60 | objectMapperCopy.addMixIn(SampleObject.class, IgnoreField3MixIn.class); 61 | 62 | objectMapperCopy.writeValueAsString(sampleObject); 63 | 64 | objectMapper.writeValueAsString(sampleObject); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestBuilders.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 5 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 6 | 7 | public class TestBuilders extends AfterburnerTestBase 8 | { 9 | // [Issue#22]: 10 | static final class ThingBuilder 11 | { 12 | private String foo; 13 | 14 | public ThingBuilder withFoo(String str) { 15 | foo = str; 16 | return this; 17 | } 18 | 19 | public Thing build() { 20 | return new Thing(foo); 21 | } 22 | } 23 | 24 | @JsonDeserialize(builder=ThingBuilder.class) 25 | static class Thing { 26 | final String foo; 27 | 28 | private Thing(String foo) { 29 | this.foo = foo; 30 | } 31 | } 32 | 33 | /* 34 | /********************************************************** 35 | /* Test methods, valid cases, non-deferred, no-mixins 36 | /********************************************************** 37 | */ 38 | 39 | private final ObjectMapper MAPPER = mapperWithModule(); 40 | 41 | public void testSimpleBuilder() throws Exception 42 | { 43 | final Thing expected = new ThingBuilder().withFoo("bar").build(); 44 | final Thing actual = MAPPER.readValue("{ \"foo\": \"bar\"}", Thing.class); 45 | 46 | assertNotNull(actual); 47 | assertNotNull(actual.foo); 48 | assertEquals(expected.foo, actual.foo); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestCollectionDeser.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.util.*; 4 | 5 | import com.fasterxml.jackson.databind.*; 6 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 7 | 8 | public class TestCollectionDeser extends AfterburnerTestBase 9 | { 10 | // [module-afterburner#36] 11 | static class CollectionBean 12 | { 13 | private Collection x = new TreeSet(); 14 | 15 | public Collection getStuff() { return x; } 16 | } 17 | 18 | static class IntBean { 19 | public int value; 20 | } 21 | 22 | /* 23 | /********************************************************************** 24 | /* Test methods 25 | /********************************************************************** 26 | */ 27 | 28 | // [module-afterburner#36] 29 | public void testIntMethod() throws Exception 30 | { 31 | ObjectMapper mapper = mapperWithModule(); 32 | mapper.configure(MapperFeature.USE_GETTERS_AS_SETTERS, true); 33 | CollectionBean bean = mapper.readValue("{\"stuff\":[\"a\",\"b\"]}", 34 | CollectionBean.class); 35 | assertEquals(2, bean.x.size()); 36 | assertEquals(TreeSet.class, bean.x.getClass()); 37 | } 38 | 39 | // [module-afterburner#56] 40 | public void testUnwrapSingleArray() throws Exception 41 | { 42 | final ObjectMapper mapper = mapperWithModule(); 43 | mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); 44 | 45 | /* 46 | final Integer intValue = mapper.readValue("[ 1 ]", Integer.class); 47 | assertEquals(Integer.valueOf(1), intValue); 48 | 49 | final String strValue = mapper.readValue("[ \"abc\" ]", String.class); 50 | assertEquals("abc", strValue); 51 | 52 | // and then via POJO. First, array of POJOs 53 | IntBean b1 = mapper.readValue(aposToQuotes("[{ 'value' : 123 }]"), IntBean.class); 54 | assertNotNull(b1); 55 | assertEquals(123, b1.value); 56 | */ 57 | 58 | // and then array of ints within POJO 59 | IntBean b2 = mapper.readValue(aposToQuotes("{ 'value' : [ 123 ] }"), IntBean.class); 60 | assertNotNull(b2); 61 | assertEquals(123, b2.value); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestConstructors.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 6 | 7 | public class TestConstructors extends AfterburnerTestBase 8 | { 9 | // [Issue#34] 10 | @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) 11 | private static class Row 12 | { 13 | private String id; 14 | 15 | public String _id() { return id; } 16 | } 17 | 18 | /* 19 | /********************************************************************** 20 | /* Test methods 21 | /********************************************************************** 22 | */ 23 | 24 | // For [Issue#34] 25 | public void testPrivateConstructor() throws Exception 26 | { 27 | ObjectMapper mapper = mapperWithModule(); 28 | Row row = mapper.readValue("{\"id\":\"x\"}", Row.class); 29 | assertNotNull(row); 30 | assertEquals("x", row._id()); 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestCreatorsDelegating.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JacksonInject; 5 | 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 8 | 9 | public class TestCreatorsDelegating extends AfterburnerTestBase 10 | { 11 | static class BooleanBean 12 | { 13 | protected Boolean value; 14 | 15 | public BooleanBean(Boolean v) { value = v; } 16 | 17 | @JsonCreator 18 | protected static BooleanBean create(Boolean value) { 19 | return new BooleanBean(value); 20 | } 21 | } 22 | 23 | // for [JACKSON-711]; should allow delegate-based one(s) too 24 | static class CtorBean711 25 | { 26 | protected String name; 27 | protected int age; 28 | 29 | @JsonCreator 30 | public CtorBean711(@JacksonInject String n, int a) 31 | { 32 | name = n; 33 | age = a; 34 | } 35 | } 36 | 37 | // for [JACKSON-711]; should allow delegate-based one(s) too 38 | static class FactoryBean711 39 | { 40 | protected String name1; 41 | protected String name2; 42 | protected int age; 43 | 44 | private FactoryBean711(int a, String n1, String n2) { 45 | age = a; 46 | name1 = n1; 47 | name2 = n2; 48 | } 49 | 50 | @JsonCreator 51 | public static FactoryBean711 create(@JacksonInject String n1, int a, @JacksonInject String n2) { 52 | return new FactoryBean711(a, n1, n2); 53 | } 54 | } 55 | 56 | /* 57 | /********************************************************** 58 | /* Unit tests 59 | /********************************************************** 60 | */ 61 | 62 | public void testBooleanDelegate() throws Exception 63 | { 64 | ObjectMapper m = mapperWithModule(); 65 | // should obviously work with booleans... 66 | BooleanBean bb = m.readValue("true", BooleanBean.class); 67 | assertEquals(Boolean.TRUE, bb.value); 68 | 69 | // but also with value conversion from String 70 | bb = m.readValue(quote("true"), BooleanBean.class); 71 | assertEquals(Boolean.TRUE, bb.value); 72 | } 73 | 74 | // As per [JACKSON-711]: should also work with delegate model (single non-annotated arg) 75 | public void testWithCtorAndDelegate() throws Exception 76 | { 77 | ObjectMapper mapper = mapperWithModule(); 78 | mapper.setInjectableValues(new InjectableValues.Std() 79 | .addValue(String.class, "Pooka") 80 | ); 81 | CtorBean711 bean = null; 82 | try { 83 | bean = mapper.readValue("38", CtorBean711.class); 84 | } catch (JsonMappingException e) { 85 | fail("Did not expect problems, got: "+e.getMessage()); 86 | } 87 | assertEquals(38, bean.age); 88 | assertEquals("Pooka", bean.name); 89 | } 90 | 91 | public void testWithFactoryAndDelegate() throws Exception 92 | { 93 | ObjectMapper mapper = mapperWithModule(); 94 | mapper.setInjectableValues(new InjectableValues.Std() 95 | .addValue(String.class, "Fygar") 96 | ); 97 | FactoryBean711 bean = null; 98 | try { 99 | bean = mapper.readValue("38", FactoryBean711.class); 100 | } catch (JsonMappingException e) { 101 | fail("Did not expect problems, got: "+e.getMessage()); 102 | } 103 | assertEquals(38, bean.age); 104 | assertEquals("Fygar", bean.name1); 105 | assertEquals("Fygar", bean.name2); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestFinalFields.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | import com.fasterxml.jackson.databind.*; 5 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 6 | 7 | public class TestFinalFields extends AfterburnerTestBase 8 | { 9 | static class Address { 10 | public int zip1, zip2; 11 | 12 | public Address() { } 13 | public Address(int z1, int z2) { 14 | zip1 = z1; 15 | zip2 = z2; 16 | } 17 | } 18 | 19 | @JsonInclude(JsonInclude.Include.NON_NULL) 20 | static class Organization 21 | { 22 | public final long id; 23 | public final String name; 24 | public final Address address; 25 | 26 | @JsonCreator 27 | public Organization(@JsonProperty("id") long id, 28 | @JsonProperty("name") String name, 29 | @JsonProperty("address") Address address) 30 | { 31 | this.id = id; 32 | this.name = name; 33 | this.address = address; 34 | } 35 | } 36 | 37 | /* 38 | /********************************************************** 39 | /* Unit tests 40 | /********************************************************** 41 | */ 42 | 43 | public void testFinalFields() throws Exception 44 | { 45 | ObjectMapper mapper = mapperWithModule(); 46 | String json = mapper.writeValueAsString(new Organization[] { 47 | new Organization(123L, "Corp", new Address(98040, 98021)) 48 | }); 49 | Organization[] result = mapper.readValue(json, Organization[].class); 50 | assertNotNull(result); 51 | assertEquals(1, result.length); 52 | assertNotNull(result[0]); 53 | assertNotNull(result[0].address); 54 | assertEquals(98021, result[0].address.zip2); 55 | } 56 | 57 | // For [Afterburner#42] 58 | 59 | public void testFinalFields42() throws Exception 60 | { 61 | JsonAddress address = new JsonAddress(-1L, "line1", "line2", "city", "state", "zip", "locale", "timezone"); 62 | JsonOrganization organization = new JsonOrganization(-1L, "name", address); 63 | ObjectMapper mapper = mapperWithModule(); 64 | String json = mapper.writeValueAsString(organization); 65 | assertNotNull(json); 66 | 67 | JsonOrganization result = mapper.readValue(json, JsonOrganization.class); 68 | assertNotNull(result); 69 | } 70 | 71 | @JsonInclude(JsonInclude.Include.NON_NULL) 72 | static class JsonAddress extends Resource { 73 | public final long id; 74 | public final String state; 75 | public final String timezone; 76 | public final String locale; 77 | public final String line1; 78 | public final String line2; 79 | public final String city; 80 | public final String zipCode; 81 | 82 | // Note: missing last 2 fields, to trigger problem 83 | @JsonCreator 84 | public JsonAddress(@JsonProperty("id") long id, 85 | @JsonProperty("line1") String line1, 86 | @JsonProperty("line2") String line2, 87 | @JsonProperty("city") String city, 88 | @JsonProperty("state") String state, 89 | @JsonProperty("zipCode") String zipCode) 90 | { 91 | this.id = id; 92 | this.line1 = line1; 93 | this.line2 = line2; 94 | this.city = city; 95 | this.state = state; 96 | this.zipCode = zipCode; 97 | this.locale = null; 98 | this.timezone = null; 99 | } 100 | 101 | public JsonAddress(long id, 102 | String line1, 103 | String line2, 104 | String city, 105 | String state, 106 | String zipCode, 107 | String locale, 108 | String timezone) 109 | { 110 | this.id = id; 111 | this.line1 = line1; 112 | this.line2 = line2; 113 | this.city = city; 114 | this.state = state; 115 | this.zipCode = zipCode; 116 | this.locale = locale; 117 | this.timezone = timezone; 118 | } 119 | } 120 | 121 | @JsonInclude(JsonInclude.Include.NON_NULL) 122 | static class JsonOrganization extends Resource { 123 | public final long id; 124 | public final String name; 125 | public final JsonAddress address; 126 | 127 | @JsonCreator 128 | public JsonOrganization(@JsonProperty("id") long id, 129 | @JsonProperty("name") String name, 130 | @JsonProperty("address") JsonAddress address) 131 | { 132 | this.id = id; 133 | this.name = name; 134 | this.address = address; 135 | } 136 | } 137 | 138 | static class Resource { } 139 | } 140 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestIssue14.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.util.*; 4 | 5 | import com.fasterxml.jackson.annotation.JsonInclude; 6 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 7 | import com.fasterxml.jackson.annotation.JsonProperty; 8 | 9 | import com.fasterxml.jackson.databind.ObjectMapper; 10 | 11 | import com.fasterxml.jackson.module.afterburner.AfterburnerModule; 12 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 13 | 14 | public class TestIssue14 extends AfterburnerTestBase 15 | { 16 | public void testIssue() throws Exception 17 | { 18 | // create this ridiculously complicated object 19 | ItemData data = new ItemData(); 20 | data.denomination = 100; 21 | Item item = new Item(); 22 | item.data = data; 23 | item.productId = 123; 24 | 25 | List itemList = new ArrayList(); 26 | itemList.add(item); 27 | 28 | PlaceOrderRequest order = new PlaceOrderRequest(); 29 | order.orderId = 68723496; 30 | order.userId = "123489043"; 31 | order.amount = 250; 32 | order.status = "placed"; 33 | order.items = itemList; 34 | 35 | final Date now = new Date(999999L); 36 | 37 | order.createdAt = now; 38 | order.updatedAt = now; 39 | 40 | ObjectMapper vanillaMapper = new ObjectMapper(); 41 | ObjectMapper abMapper = new ObjectMapper(); 42 | abMapper.registerModule(new AfterburnerModule()); 43 | 44 | // First: ensure that serialization produces identical output 45 | 46 | String origJson = vanillaMapper 47 | .writerWithDefaultPrettyPrinter() 48 | .writeValueAsString(order); 49 | 50 | String abJson = abMapper 51 | .writerWithDefaultPrettyPrinter() 52 | .writeValueAsString(order); 53 | 54 | assertEquals(origJson, abJson); 55 | 56 | // Then read the string and turn it back into an object 57 | // this will cause an exception unless the AfterburnerModule is commented out 58 | order = abMapper.readValue(abJson, PlaceOrderRequest.class); 59 | assertNotNull(order); 60 | assertEquals(250, order.amount); 61 | } 62 | } 63 | 64 | class PlaceOrderRequest { 65 | @JsonProperty("id") public long orderId; 66 | @JsonProperty("from") public String userId; 67 | public int amount; 68 | public String status; 69 | public List items; 70 | @JsonProperty("created_at") public Date createdAt; 71 | @JsonProperty("updated_at") public Date updatedAt; 72 | } 73 | 74 | class Item { 75 | @JsonProperty("product_id") public int productId; 76 | public int quantity; 77 | public ItemData data; 78 | } 79 | 80 | @JsonInclude(Include.NON_NULL) 81 | class ItemData { 82 | public int denomination; 83 | public List bets; 84 | } 85 | 86 | class VLTBet { 87 | public int index; 88 | public String selection; 89 | public int stake; 90 | public int won; 91 | } 92 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestNonStaticInner.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 5 | 6 | public class TestNonStaticInner extends AfterburnerTestBase 7 | { 8 | static class Parent { 9 | 10 | private Child child; 11 | 12 | public Child getChild() { 13 | return child; 14 | } 15 | 16 | public void setChild(Child child) { 17 | this.child = child; 18 | } 19 | 20 | public /* not static */ class Child { 21 | private boolean value; 22 | 23 | public boolean isValue() { 24 | return value; 25 | } 26 | 27 | public void setValue(boolean value) { 28 | this.value = value; 29 | } 30 | } 31 | } 32 | 33 | public void testInnerClass() throws Exception { 34 | final ObjectMapper MAPPER = mapperWithModule(); 35 | // final ObjectMapper MAPPER = new ObjectMapper(); 36 | 37 | Parent parent = MAPPER.readValue("{\"child\":{\"value\":true}}", Parent.class); 38 | 39 | assertTrue(parent.getChild().isValue()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestPolymorphic.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | 7 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 8 | 9 | public class TestPolymorphic extends AfterburnerTestBase 10 | { 11 | static class Envelope { 12 | @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.EXTERNAL_PROPERTY, property="class") 13 | private Object payload; 14 | 15 | public Envelope(@JsonProperty("payload") Object payload) { 16 | this.payload = payload; 17 | } 18 | public Envelope() { } 19 | 20 | @JsonProperty 21 | public Object getPayload() { 22 | return payload; 23 | } 24 | } 25 | 26 | static class Payload { 27 | private String something; 28 | 29 | public Payload(@JsonProperty("something") String something) { 30 | this.something = something; 31 | } 32 | @JsonProperty 33 | public Object getSomething() { 34 | return something; 35 | } 36 | } 37 | 38 | public void testAfterburner() throws Exception { 39 | ObjectMapper mapper = mapperWithModule(); 40 | Envelope envelope = new Envelope(new Payload("test")); 41 | String json = mapper.writeValueAsString(envelope); 42 | Envelope result = mapper.readValue(json, Envelope.class); 43 | 44 | assertNotNull(result); 45 | assertNotNull(result.payload); 46 | assertEquals(Payload.class, result.payload.getClass()); 47 | } 48 | 49 | // for [module-afterburner#58]; although seems to be due to databind issue 50 | public void testPolymorphicIssue58() throws Exception 51 | { 52 | final String CLASS = Payload.class.getName(); 53 | 54 | ObjectMapper mapper = mapperWithModule(); 55 | 56 | // First, case that has been working always 57 | final String successCase = "{\"payload\":{\"something\":\"test\"},\"class\":\""+CLASS+"\"}"; 58 | Envelope envelope1 = mapper.readValue(successCase, Envelope.class); 59 | assertNotNull(envelope1); 60 | assertEquals(Payload.class, envelope1.payload.getClass()); 61 | 62 | // and then re-ordered case that was problematic 63 | final String failCase = "{\"class\":\""+CLASS+"\",\"payload\":{\"something\":\"test\"}}"; 64 | Envelope envelope2 = mapper.readValue(failCase, Envelope.class); 65 | assertNotNull(envelope2); 66 | assertEquals(Payload.class, envelope2.payload.getClass()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestPolymorphicCreators.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | 5 | import com.fasterxml.jackson.databind.*; 6 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 7 | 8 | /** 9 | * Unit tests for verifying that it is possible to annotate 10 | * various kinds of things with {@link JsonCreator} annotation. 11 | */ 12 | public class TestPolymorphicCreators extends AfterburnerTestBase 13 | { 14 | static class Animal 15 | { 16 | // All animals have names, for our demo purposes... 17 | public String name; 18 | 19 | protected Animal() { } 20 | 21 | /** 22 | * Creator method that can instantiate instances of 23 | * appropriate polymoprphic type 24 | */ 25 | @JsonCreator 26 | public static Animal create(@JsonProperty("type") String type) 27 | { 28 | if ("dog".equals(type)) { 29 | return new Dog(); 30 | } 31 | if ("cat".equals(type)) { 32 | return new Cat(); 33 | } 34 | throw new IllegalArgumentException("No such animal type ('"+type+"')"); 35 | } 36 | } 37 | 38 | static class Dog extends Animal 39 | { 40 | double barkVolume; // in decibels 41 | public Dog() { } 42 | public void setBarkVolume(double v) { barkVolume = v; } 43 | } 44 | 45 | static class Cat extends Animal 46 | { 47 | boolean likesCream; 48 | public int lives; 49 | public Cat() { } 50 | public void setLikesCream(boolean likesCreamSurely) { likesCream = likesCreamSurely; } 51 | } 52 | 53 | abstract static class AbstractRoot 54 | { 55 | private final String opt; 56 | 57 | private AbstractRoot(String opt) { 58 | this.opt = opt; 59 | } 60 | 61 | @JsonCreator 62 | public static final AbstractRoot make(@JsonProperty("which") int which, 63 | @JsonProperty("opt") String opt) { 64 | if(1 == which) { 65 | return new One(opt); 66 | } 67 | throw new RuntimeException("cannot instantiate " + which); 68 | } 69 | 70 | abstract public int getWhich(); 71 | 72 | public final String getOpt() { 73 | return opt; 74 | } 75 | } 76 | 77 | static final class One extends AbstractRoot { 78 | private One(String opt) { 79 | super(opt); 80 | } 81 | 82 | @Override public int getWhich() { 83 | return 1; 84 | } 85 | } 86 | 87 | /* 88 | /********************************************************** 89 | /* Actual tests 90 | /********************************************************** 91 | */ 92 | 93 | private final ObjectMapper MAPPER = mapperWithModule(); 94 | 95 | /** 96 | * Simple test to verify that it is possible to implement polymorphic 97 | * deserialization manually. 98 | */ 99 | public void testManualPolymorphicDog() throws Exception 100 | { 101 | // first, a dog, start with type 102 | Animal animal = MAPPER.readValue("{ \"type\":\"dog\", \"name\":\"Fido\", \"barkVolume\" : 95.0 }", Animal.class); 103 | assertEquals(Dog.class, animal.getClass()); 104 | assertEquals("Fido", animal.name); 105 | assertEquals(95.0, ((Dog) animal).barkVolume); 106 | } 107 | 108 | public void testManualPolymorphicCatBasic() throws Exception 109 | { 110 | // and finally, lactose-intolerant, but otherwise robust super-cat: 111 | Animal animal = MAPPER.readValue("{ \"name\" : \"Macavity\", \"type\":\"cat\", \"lives\":18, \"likesCream\":false }", Animal.class); 112 | assertEquals(Cat.class, animal.getClass()); 113 | assertEquals("Macavity", animal.name); // ... there's no one like Macavity! 114 | Cat cat = (Cat) animal; 115 | assertEquals(18, cat.lives); 116 | // ok, he can't drink dairy products. Let's verify: 117 | assertEquals(false, cat.likesCream); 118 | } 119 | 120 | public void testManualPolymorphicCatWithReorder() throws Exception 121 | { 122 | // Then cat; shuffle order to mandate buffering 123 | Animal animal = MAPPER.readValue("{ \"likesCream\":true, \"name\" : \"Venla\", \"type\":\"cat\" }", Animal.class); 124 | assertEquals(Cat.class, animal.getClass()); 125 | assertEquals("Venla", animal.name); 126 | // bah, of course cats like cream. But let's ensure Jackson won't mess with laws of nature! 127 | assertTrue(((Cat) animal).likesCream); 128 | } 129 | 130 | public void testManualPolymorphicWithNumbered() throws Exception 131 | { 132 | final ObjectWriter w = MAPPER.writerFor(AbstractRoot.class); 133 | final ObjectReader r = MAPPER.readerFor(AbstractRoot.class); 134 | 135 | AbstractRoot input = AbstractRoot.make(1, "oh hai!"); 136 | String json = w.writeValueAsString(input); 137 | AbstractRoot result = r.readValue(json); 138 | assertNotNull(result); 139 | assertEquals("oh hai!", result.getOpt()); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestSingleArgCtors.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 6 | 7 | public class TestSingleArgCtors extends AfterburnerTestBase 8 | { 9 | static class Node { 10 | public String name; 11 | 12 | public int value; 13 | 14 | public Node() { } 15 | 16 | @JsonCreator 17 | public Node(String n) { 18 | name = n; 19 | value = -1; 20 | } 21 | } 22 | 23 | /* 24 | /********************************************************** 25 | /* Test methods 26 | /********************************************************** 27 | */ 28 | 29 | private final ObjectMapper MAPPER = mapperWithModule(); 30 | 31 | public void testSingleStringArgCtor() throws Exception 32 | { 33 | Node bean = MAPPER.readValue(quote("Foobar"), Node.class); 34 | assertNotNull(bean); 35 | assertEquals(-1, bean.value); 36 | assertEquals("Foobar", bean.name); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestStdDeserializerOverrides.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | import com.fasterxml.jackson.databind.*; 7 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 8 | import com.fasterxml.jackson.databind.deser.Deserializers; 9 | import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 10 | import com.fasterxml.jackson.databind.module.SimpleModule; 11 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 12 | 13 | @SuppressWarnings("serial") 14 | public class TestStdDeserializerOverrides extends AfterburnerTestBase 15 | { 16 | static class ClassWithPropOverrides 17 | { 18 | public String a; 19 | 20 | @JsonDeserialize(using=MyStringDeserializer.class) 21 | public String b; 22 | } 23 | 24 | static class MyStringDeserializer extends StdDeserializer 25 | { 26 | public MyStringDeserializer() { super(String.class); } 27 | 28 | @Override 29 | public String deserialize(JsonParser p, DeserializationContext ctxt) 30 | throws IOException, JsonProcessingException { 31 | return "Foo:"+p.getText(); 32 | } 33 | } 34 | 35 | // for [module-afterburner#59] 36 | static class Issue59Bean { 37 | public String field; 38 | } 39 | 40 | static class DeAmpDeserializer extends StdDeserializer 41 | { 42 | public DeAmpDeserializer() { super(String.class); } 43 | 44 | @Override 45 | public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 46 | return p.getText().replaceAll("&", "&"); 47 | } 48 | } 49 | 50 | /* 51 | /********************************************************************** 52 | /* Test methods 53 | /********************************************************************** 54 | */ 55 | 56 | public void testFiveMinuteDoc() throws Exception 57 | { 58 | ObjectMapper plainMapper = new ObjectMapper(); 59 | ObjectMapper abMapper = mapperWithModule(); 60 | final String JSON = "{\"a\":\"a\",\"b\":\"b\"}"; 61 | 62 | ClassWithPropOverrides vanilla = plainMapper.readValue(JSON, ClassWithPropOverrides.class); 63 | ClassWithPropOverrides burnt = abMapper.readValue(JSON, ClassWithPropOverrides.class); 64 | 65 | assertEquals("a", vanilla.a); 66 | assertEquals("Foo:b", vanilla.b); 67 | 68 | assertEquals("a", burnt.a); 69 | assertEquals("Foo:b", burnt.b); 70 | } 71 | 72 | public void testStringDeserOverideNoAfterburner() throws Exception 73 | { 74 | final String json = "{\"field\": \"value & value\"}"; 75 | final String EXP = "value & value"; 76 | Issue59Bean resultVanilla = new ObjectMapper() 77 | .registerModule(new SimpleModule("module", Version.unknownVersion()) 78 | .addDeserializer(String.class, new DeAmpDeserializer())) 79 | .readValue(json, Issue59Bean.class); 80 | assertEquals(EXP, resultVanilla.field); 81 | } 82 | 83 | // for [module-afterburner#59] 84 | public void testStringDeserOverideWithAfterburner() throws Exception 85 | { 86 | final String json = "{\"field\": \"value & value\"}"; 87 | final String EXP = "value & value"; 88 | 89 | final Module module = new SimpleModule("module", Version.unknownVersion()) { 90 | @Override 91 | public void setupModule(SetupContext context) { 92 | context.addDeserializers( 93 | new Deserializers.Base() { 94 | @Override 95 | public JsonDeserializer findBeanDeserializer( 96 | JavaType type, 97 | DeserializationConfig config, 98 | BeanDescription beanDesc) 99 | throws JsonMappingException { 100 | if (type.hasRawClass(String.class)) { 101 | return new DeAmpDeserializer(); 102 | } 103 | return null; 104 | } 105 | }); 106 | } 107 | }; 108 | 109 | // but then fails with Afterburner 110 | Issue59Bean resultAB = mapperWithModule() 111 | .registerModule(module) 112 | .readValue(json, Issue59Bean.class); 113 | assertEquals(EXP, resultAB.field); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/deser/TestTreeConversions.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.deser; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | import com.fasterxml.jackson.databind.JsonNode; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 8 | 9 | public class TestTreeConversions extends AfterburnerTestBase 10 | { 11 | @JsonIgnoreProperties(ignoreUnknown = true) 12 | public static class Occupancy { 13 | private Integer max; 14 | private Guests adults; 15 | private Guests children; 16 | 17 | public Occupancy() { 18 | } 19 | 20 | public Occupancy(Integer max, Guests adults, Guests children) { 21 | this.max = max; 22 | this.adults = adults; 23 | this.children = children; 24 | } 25 | 26 | public Integer getMax() { 27 | return max; 28 | } 29 | 30 | public Guests getAdults() { 31 | return adults; 32 | } 33 | 34 | public Guests getChildren() { 35 | return children; 36 | } 37 | 38 | } 39 | 40 | @JsonIgnoreProperties(ignoreUnknown = true) 41 | public static class Guests { 42 | 43 | private Integer min; 44 | private Integer max; 45 | 46 | public Guests() { 47 | } 48 | 49 | public Guests(Integer min, Integer max) { 50 | this.min = min; 51 | this.max = max; 52 | } 53 | 54 | public Integer getMin() { 55 | return min; 56 | } 57 | 58 | public Integer getMax() { 59 | return max; 60 | } 61 | 62 | } 63 | /* 64 | /********************************************************** 65 | /* Actual tests 66 | /********************************************************** 67 | */ 68 | 69 | private final ObjectMapper MAPPER = mapperWithModule(); 70 | 71 | public void testConversion() throws Exception 72 | { 73 | final JsonNode node = MAPPER.readTree("{" + 74 | "\"max\":3," + 75 | "\"adults\": {" + 76 | "\"min\":1" + 77 | "}," + 78 | "\"children\":{" + 79 | "\"min\":1," + 80 | "\"max\":2" + 81 | "}" + 82 | "}"); 83 | 84 | final Occupancy occupancy = MAPPER.readerFor(Occupancy.class).readValue(node); 85 | 86 | assertNull(occupancy.getAdults().getMax()); 87 | assertEquals(Integer.valueOf(2), occupancy.getChildren().getMax()); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/roundtrip/AbstractSettersTest.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.roundtrip; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | import com.fasterxml.jackson.databind.*; 5 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 6 | 7 | // for [issue#47] 8 | public class AbstractSettersTest extends AfterburnerTestBase 9 | { 10 | @JsonTypeInfo( 11 | use = JsonTypeInfo.Id.NAME, 12 | include = JsonTypeInfo.As.PROPERTY, 13 | property = "type") 14 | @JsonSubTypes({ 15 | @JsonSubTypes.Type(value = FooImpl1.class, name = "impl1") }) 16 | @JsonInclude(JsonInclude.Include.NON_NULL) 17 | public interface FooBase extends Cloneable 18 | { 19 | String getId(); 20 | void setId(String id); 21 | 22 | FooBase clone() throws CloneNotSupportedException; 23 | } 24 | 25 | static class FooImpl1 implements FooBase { 26 | protected String id, revision, category; 27 | 28 | @Override 29 | public String getId() { return id; } 30 | 31 | @Override 32 | public void setId(String id) { this.id = id; } 33 | 34 | @Override 35 | public FooBase clone() throws CloneNotSupportedException { 36 | return this; 37 | } 38 | } 39 | 40 | /* 41 | /********************************************************** 42 | /* Test methods 43 | /********************************************************** 44 | */ 45 | 46 | private final ObjectMapper MAPPER = mapperWithModule(); 47 | 48 | public void testSimpleConstructor() throws Exception 49 | { 50 | FooImpl1 item = new FooImpl1(); 51 | String string = MAPPER.writer() 52 | .without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) 53 | .writeValueAsString(item); 54 | FooBase read = MAPPER.readValue(string, FooBase.class); 55 | assertNotNull(read); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/roundtrip/BiggerDataTest.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.roundtrip; 2 | 3 | import java.util.*; 4 | 5 | import com.fasterxml.jackson.databind.*; 6 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 7 | 8 | /** 9 | * Bigger test to try to do smoke-testing of overall functionality, 10 | * using more sizable (500k of JSON, 200k of encoded data) dataset. 11 | * Should tease out at least some of boundary conditions. 12 | */ 13 | public class BiggerDataTest extends AfterburnerTestBase 14 | { 15 | static class Citm 16 | { 17 | public Map areaNames; 18 | public Map audienceSubCategoryNames; 19 | public Map blockNames; 20 | public Map seatCategoryNames; 21 | public Map subTopicNames; 22 | public Map subjectNames; 23 | public Map topicNames; 24 | public Map topicSubTopics; 25 | public Map venueNames; 26 | 27 | public Map events; 28 | public List performances; 29 | } 30 | 31 | static class Event 32 | { 33 | public int id; 34 | public String name; 35 | public String description; 36 | public String subtitle; 37 | public String logo; 38 | public int subjectCode; 39 | public int[] topicIds; 40 | public LinkedHashSet subTopicIds; 41 | } 42 | 43 | static class Performance 44 | { 45 | public int id; 46 | public int eventId; 47 | public String name; 48 | public String description; 49 | public String logo; 50 | 51 | public List prices; 52 | public List seatCategories; 53 | 54 | public long start; 55 | public String seatMapImage; 56 | public String venueCode; 57 | } 58 | 59 | static class Price { 60 | public int amount; 61 | public int audienceSubCategoryId; 62 | public int seatCategoryId; 63 | } 64 | 65 | static class SeatCategory { 66 | public int seatCategoryId; 67 | public List areas; 68 | } 69 | 70 | static class Area { 71 | public int areaId; 72 | public int[] blockIds; 73 | } 74 | 75 | /* 76 | /********************************************************** 77 | /* Test methods 78 | /********************************************************** 79 | */ 80 | 81 | private final ObjectMapper MAPPER = mapperWithModule(); 82 | 83 | public void testReading() throws Exception 84 | { 85 | Citm citm0 = MAPPER.readValue(getClass().getResourceAsStream("/data/citm_catalog.json"), 86 | Citm.class); 87 | 88 | byte[] cbor = MAPPER.writeValueAsBytes(citm0); 89 | 90 | Citm citm = MAPPER.readValue(cbor, Citm.class); 91 | 92 | assertNotNull(citm); 93 | assertNotNull(citm.areaNames); 94 | assertEquals(17, citm.areaNames.size()); 95 | assertNotNull(citm.events); 96 | assertEquals(184, citm.events.size()); 97 | 98 | assertNotNull(citm.seatCategoryNames); 99 | assertEquals(64, citm.seatCategoryNames.size()); 100 | assertNotNull(citm.subTopicNames); 101 | assertEquals(19, citm.subTopicNames.size()); 102 | assertNotNull(citm.subjectNames); 103 | assertEquals(0, citm.subjectNames.size()); 104 | assertNotNull(citm.topicNames); 105 | assertEquals(4, citm.topicNames.size()); 106 | assertNotNull(citm.topicSubTopics); 107 | assertEquals(4, citm.topicSubTopics.size()); 108 | assertNotNull(citm.venueNames); 109 | assertEquals(1, citm.venueNames.size()); 110 | } 111 | 112 | public void testRoundTrip() throws Exception 113 | { 114 | Citm citm0 = MAPPER.readValue(getClass().getResourceAsStream("/data/citm_catalog.json"), 115 | Citm.class); 116 | 117 | byte[] cbor = MAPPER.writeValueAsBytes(citm0); 118 | Citm citm = MAPPER.readValue(cbor, Citm.class); 119 | 120 | byte[] smile1 = MAPPER.writeValueAsBytes(citm); 121 | Citm citm2 = MAPPER.readValue(smile1, Citm.class); 122 | byte[] smile2 = MAPPER.writeValueAsBytes(citm2); 123 | 124 | assertEquals(smile1.length, smile2.length); 125 | 126 | assertNotNull(citm.areaNames); 127 | assertEquals(17, citm.areaNames.size()); 128 | assertNotNull(citm.events); 129 | assertEquals(184, citm.events.size()); 130 | 131 | assertEquals(citm.seatCategoryNames.size(), citm2.seatCategoryNames.size()); 132 | assertEquals(citm.subTopicNames.size(), citm2.subTopicNames.size()); 133 | assertEquals(citm.subjectNames.size(), citm2.subjectNames.size()); 134 | assertEquals(citm.topicNames.size(), citm2.topicNames.size()); 135 | assertEquals(citm.topicSubTopics.size(), citm2.topicSubTopics.size()); 136 | assertEquals(citm.venueNames.size(), citm2.venueNames.size()); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/roundtrip/JavaxTypesTest.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.roundtrip; 2 | 3 | import javax.security.auth.AuthPermission; 4 | import javax.xml.datatype.DatatypeFactory; 5 | import javax.xml.datatype.XMLGregorianCalendar; 6 | 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 9 | 10 | /** 11 | * Simple tests to try to see that handling of semi-standard types 12 | * from javax.* work. 13 | */ 14 | public class JavaxTypesTest extends AfterburnerTestBase 15 | { 16 | final ObjectMapper MAPPER = mapperWithModule(); 17 | 18 | public void testGregorianCalendar() throws Exception 19 | { 20 | DatatypeFactory f = DatatypeFactory.newInstance(); 21 | XMLGregorianCalendar in = f.newXMLGregorianCalendar(); 22 | in.setYear(2014); 23 | in.setMonth(3); 24 | 25 | String json = MAPPER.writeValueAsString(in); 26 | assertNotNull(json); 27 | XMLGregorianCalendar out = MAPPER.readValue(json, XMLGregorianCalendar.class); 28 | assertNotNull(out); 29 | 30 | // minor sanity check 31 | assertEquals(in.getYear(), out.getYear()); 32 | } 33 | 34 | public void testAuthPermission() throws Exception 35 | { 36 | AuthPermission in = new AuthPermission("foo"); 37 | String json = MAPPER.writeValueAsString(in); 38 | assertNotNull(json); 39 | 40 | // actually, deserialization won't work by default. So let's just check 41 | // some lexical aspects 42 | if (!json.contains("\"name\":")) { 43 | fail("Unexpected JSON, missing 'name' property: "+json); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/roundtrip/MediaItem.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.roundtrip; 2 | 3 | import java.util.*; 4 | 5 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 6 | 7 | @JsonPropertyOrder({"content", "images", "bogus"}) 8 | public class MediaItem 9 | { 10 | public enum Player { JAVA, FLASH; } 11 | public enum Size { SMALL, LARGE; } 12 | 13 | private List _photos; 14 | private Content _content; 15 | 16 | // just to exercise boolean access 17 | public boolean bogus = true; 18 | 19 | public MediaItem() { } 20 | 21 | public MediaItem(Content c) 22 | { 23 | _content = c; 24 | } 25 | 26 | public void addPhoto(Photo p) { 27 | if (_photos == null) { 28 | _photos = new ArrayList(); 29 | } 30 | _photos.add(p); 31 | } 32 | 33 | public List getImages() { return _photos; } 34 | public void setImages(List p) { _photos = p; } 35 | 36 | public Content getContent() { return _content; } 37 | public void setContent(Content c) { _content = c; } 38 | 39 | /* 40 | /********************************************************** 41 | /* Helper types 42 | /********************************************************** 43 | */ 44 | 45 | @JsonPropertyOrder({"uri","title","width","height","size"}) 46 | public static class Photo 47 | { 48 | private String _uri; 49 | private String _title; 50 | private int _width; 51 | private int _height; 52 | private Size _size; 53 | 54 | public Photo() {} 55 | public Photo(String uri, String title, int w, int h, Size s) 56 | { 57 | _uri = uri; 58 | _title = title; 59 | _width = w; 60 | _height = h; 61 | _size = s; 62 | } 63 | 64 | public String getUri() { return _uri; } 65 | public String getTitle() { return _title; } 66 | public int getWidth() { return _width; } 67 | public int getHeight() { return _height; } 68 | public Size getSize() { return _size; } 69 | 70 | public void setUri(String u) { _uri = u; } 71 | public void setTitle(String t) { _title = t; } 72 | public void setWidth(int w) { _width = w; } 73 | public void setHeight(int h) { _height = h; } 74 | public void setSize(Size s) { _size = s; } 75 | } 76 | 77 | @JsonPropertyOrder({"uri","title","width","height","format","duration","size","bitrate","persons","player","copyright"}) 78 | public static class Content 79 | { 80 | private Player _player; 81 | private String _uri; 82 | private String _title; 83 | private int _width; 84 | private int _height; 85 | private String _format; 86 | private long _duration; 87 | private long _size; 88 | private int _bitrate; 89 | private List _persons; 90 | private String _copyright; 91 | 92 | public Content() { } 93 | 94 | public void addPerson(String p) { 95 | if (_persons == null) { 96 | _persons = new ArrayList(); 97 | } 98 | _persons.add(p); 99 | } 100 | 101 | public Player getPlayer() { return _player; } 102 | public String getUri() { return _uri; } 103 | public String getTitle() { return _title; } 104 | public int getWidth() { return _width; } 105 | public int getHeight() { return _height; } 106 | public String getFormat() { return _format; } 107 | public long getDuration() { return _duration; } 108 | public long getSize() { return _size; } 109 | public int getBitrate() { return _bitrate; } 110 | public List getPersons() { return _persons; } 111 | public String getCopyright() { return _copyright; } 112 | 113 | public void setPlayer(Player p) { _player = p; } 114 | public void setUri(String u) { _uri = u; } 115 | public void setTitle(String t) { _title = t; } 116 | public void setWidth(int w) { _width = w; } 117 | public void setHeight(int h) { _height = h; } 118 | public void setFormat(String f) { _format = f; } 119 | public void setDuration(long d) { _duration = d; } 120 | public void setSize(long s) { _size = s; } 121 | public void setBitrate(int b) { _bitrate = b; } 122 | public void setPersons(List p) { _persons = p; } 123 | public void setCopyright(String c) { _copyright = c; } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/roundtrip/MediaItemRoundtripTest.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.roundtrip; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | 5 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 6 | 7 | /** 8 | * Let's use a non-trivial POJO from "jvm-serializers" benchmark as 9 | * sort of sanity check. 10 | */ 11 | public class MediaItemRoundtripTest extends AfterburnerTestBase 12 | { 13 | private final ObjectMapper MAPPER = mapperWithModule(); 14 | 15 | public void testSimple() throws Exception 16 | { 17 | MediaItem input = buildItem(); 18 | 19 | String json = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(input); 20 | MediaItem result = MAPPER.readValue(json, MediaItem.class); 21 | 22 | String json2 = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(result); 23 | 24 | assertEquals(json, json2); 25 | } 26 | 27 | private MediaItem buildItem() { 28 | MediaItem.Content content = new MediaItem.Content(); 29 | content.setUri("http://javaone.com/keynote.mpg"); 30 | content.setTitle("Javaone Keynote"); 31 | content.setWidth(640); 32 | content.setHeight(480); 33 | content.setFormat("video/mpg4"); 34 | content.setDuration(18000000); 35 | content.setSize(58982400L); 36 | content.setBitrate(262144); 37 | content.setPlayer(MediaItem.Player.JAVA); 38 | content.setCopyright("None"); 39 | content.addPerson("Bill Gates"); 40 | content.addPerson("Steve Jobs"); 41 | 42 | MediaItem item = new MediaItem(content); 43 | item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_large.jpg", "Javaone Keynote", 44 | 1024, 768, MediaItem.Size.LARGE)); 45 | item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_small.jpg", "Javaone Keynote", 46 | 320, 240, MediaItem.Size.SMALL)); 47 | return item; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/roundtrip/POJOAsArrayTest.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.roundtrip; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 5 | import com.fasterxml.jackson.annotation.JsonFormat.Shape; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.fasterxml.jackson.databind.SerializationFeature; 8 | import com.fasterxml.jackson.databind.introspect.Annotated; 9 | import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; 10 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 11 | 12 | // NOTE: copied almost verbatim from jackson-databind tests 13 | public class POJOAsArrayTest extends AfterburnerTestBase 14 | { 15 | static class Pojo 16 | { 17 | @JsonFormat(shape=JsonFormat.Shape.ARRAY) 18 | public PojoValue value; 19 | 20 | public Pojo() { } 21 | public Pojo(String name, int x, int y, boolean c) { 22 | value = new PojoValue(name, x, y, c); 23 | } 24 | } 25 | 26 | // note: must be serialized/deserialized alphabetically; fields NOT declared in that order 27 | @JsonPropertyOrder(alphabetic=true) 28 | static class PojoValue 29 | { 30 | public int x, y; 31 | public String name; 32 | public boolean complete; 33 | 34 | public PojoValue() { } 35 | public PojoValue(String name, int x, int y, boolean c) { 36 | this.name = name; 37 | this.x = x; 38 | this.y = y; 39 | this.complete = c; 40 | } 41 | } 42 | 43 | @JsonPropertyOrder(alphabetic=true) 44 | @JsonFormat(shape=JsonFormat.Shape.ARRAY) 45 | static class FlatPojo 46 | { 47 | public int x, y; 48 | public String name; 49 | public boolean complete; 50 | 51 | public FlatPojo() { } 52 | public FlatPojo(String name, int x, int y, boolean c) { 53 | this.name = name; 54 | this.x = x; 55 | this.y = y; 56 | this.complete = c; 57 | } 58 | } 59 | 60 | static class ForceArraysIntrospector extends JacksonAnnotationIntrospector 61 | { 62 | private static final long serialVersionUID = 1L; 63 | 64 | @Override 65 | public JsonFormat.Value findFormat(Annotated a) { 66 | return new JsonFormat.Value().withShape(JsonFormat.Shape.ARRAY); 67 | } 68 | } 69 | 70 | static class A { 71 | public B value = new B(); 72 | } 73 | 74 | @JsonPropertyOrder(alphabetic=true) 75 | static class B { 76 | public int x = 1; 77 | public int y = 2; 78 | } 79 | 80 | // for [JACKSON-805] 81 | @JsonFormat(shape=Shape.ARRAY) 82 | static class SingleBean { 83 | public String name = "foo"; 84 | } 85 | 86 | @JsonPropertyOrder(alphabetic=true) 87 | @JsonFormat(shape=Shape.ARRAY) 88 | static class TwoStringsBean { 89 | public String bar = null; 90 | public String foo = "bar"; 91 | } 92 | 93 | /* 94 | /***************************************************** 95 | /* Basic tests 96 | /***************************************************** 97 | */ 98 | 99 | final ObjectMapper MAPPER = mapperWithModule(); 100 | 101 | /** 102 | * Test that verifies that property annotation works 103 | */ 104 | public void testReadSimplePropertyValue() throws Exception 105 | { 106 | String json = "{\"value\":[true,\"Foobar\",42,13]}"; 107 | Pojo p = MAPPER.readValue(json, Pojo.class); 108 | assertNotNull(p.value); 109 | assertTrue(p.value.complete); 110 | assertEquals("Foobar", p.value.name); 111 | assertEquals(42, p.value.x); 112 | assertEquals(13, p.value.y); 113 | } 114 | 115 | /** 116 | * Test that verifies that Class annotation works 117 | */ 118 | public void testReadSimpleRootValue() throws Exception 119 | { 120 | String json = "[false,\"Bubba\",1,2]"; 121 | FlatPojo p = MAPPER.readValue(json, FlatPojo.class); 122 | assertFalse(p.complete); 123 | assertEquals("Bubba", p.name); 124 | assertEquals(1, p.x); 125 | assertEquals(2, p.y); 126 | } 127 | 128 | /** 129 | * Test that verifies that property annotation works 130 | */ 131 | public void testWriteSimplePropertyValue() throws Exception 132 | { 133 | String json = MAPPER.writeValueAsString(new Pojo("Foobar", 42, 13, true)); 134 | // will have wrapper POJO, then POJO-as-array.. 135 | assertEquals("{\"value\":[true,\"Foobar\",42,13]}", json); 136 | } 137 | 138 | /** 139 | * Test that verifies that Class annotation works 140 | */ 141 | public void testWriteSimpleRootValue() throws Exception 142 | { 143 | String json = MAPPER.writeValueAsString(new FlatPojo("Bubba", 1, 2, false)); 144 | // will have wrapper POJO, then POJO-as-array.. 145 | assertEquals("[false,\"Bubba\",1,2]", json); 146 | } 147 | 148 | // [Issue#223] 149 | public void testNullColumn() throws Exception 150 | { 151 | assertEquals("[null,\"bar\"]", MAPPER.writeValueAsString(new TwoStringsBean())); 152 | } 153 | 154 | /* 155 | /***************************************************** 156 | /* Compatibility with "single-elem as array" feature 157 | /***************************************************** 158 | */ 159 | 160 | public void testSerializeAsArrayWithSingleProperty() throws Exception { 161 | ObjectMapper mapper = mapperWithModule(); 162 | mapper.enable(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED); 163 | String json = mapper.writeValueAsString(new SingleBean()); 164 | assertEquals("\"foo\"", json); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/ser/CustomBeanPropertyWriterTest.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import java.util.List; 4 | 5 | import com.fasterxml.jackson.annotation.JsonInclude; 6 | import com.fasterxml.jackson.core.*; 7 | import com.fasterxml.jackson.databind.*; 8 | import com.fasterxml.jackson.databind.module.SimpleModule; 9 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 10 | import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; 11 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 12 | 13 | // for [afterburner#52] 14 | public class CustomBeanPropertyWriterTest extends AfterburnerTestBase 15 | { 16 | static class SampleObject { 17 | public String field1; 18 | public Integer field2; 19 | public Integer field3; 20 | 21 | protected SampleObject() { } 22 | public SampleObject(String field1, Integer field2, Integer field3) { 23 | this.field1 = field1; 24 | this.field2 = field2; 25 | this.field3 = field3; 26 | } 27 | } 28 | 29 | static class Only2BeanSerializerModifier extends BeanSerializerModifier { 30 | @Override 31 | public List changeProperties(SerializationConfig config, BeanDescription beanDesc, List props) 32 | { 33 | for (int i = 0, len = props.size(); i < len; ++i) { 34 | BeanPropertyWriter w = props.get(i); 35 | if (Integer.class.isAssignableFrom(w.getType().getRawClass())) { 36 | props.set(i, new Only2BeanPropertyWriter(w)); 37 | } 38 | } 39 | return props; 40 | } 41 | } 42 | 43 | @SuppressWarnings("serial") 44 | static class Only2BeanPropertyWriter extends BeanPropertyWriter 45 | { 46 | protected Only2BeanPropertyWriter(BeanPropertyWriter base) { 47 | super(base); 48 | } 49 | 50 | @Override 51 | public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) throws Exception { 52 | Object val = get(bean); 53 | if((val == null || !val.equals(2)) && _nullSerializer == null) { 54 | return; 55 | } 56 | super.serializeAsField(bean, jgen, prov); 57 | } 58 | } 59 | 60 | public void testCustomPropertyWriter() throws Exception 61 | { 62 | ObjectMapper objectMapper = mapperWithModule(); 63 | SimpleModule simpleModule = new SimpleModule(); 64 | simpleModule.setSerializerModifier(new Only2BeanSerializerModifier()); 65 | objectMapper.registerModule(simpleModule); 66 | objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 67 | 68 | SampleObject sampleObject = new SampleObject(null, 2, 3); 69 | String json = objectMapper.writeValueAsString(sampleObject); 70 | 71 | assertEquals("{\"field2\":2}", json); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/ser/JsonAppendTest.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.*; 5 | import com.fasterxml.jackson.databind.annotation.JsonAppend; 6 | import com.fasterxml.jackson.databind.cfg.MapperConfig; 7 | import com.fasterxml.jackson.databind.introspect.AnnotatedClass; 8 | import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; 9 | import com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter; 10 | import com.fasterxml.jackson.databind.util.Annotations; 11 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 12 | 13 | // most for [module-afterburner#57] 14 | public class JsonAppendTest extends AfterburnerTestBase 15 | { 16 | @JsonAppend(props = @JsonAppend.Prop(name = "virtual", value = MyVirtualPropertyWriter.class)) 17 | public static class Pojo { 18 | public final String name; 19 | public Pojo(String name) { 20 | this.name = name; 21 | } 22 | } 23 | 24 | @SuppressWarnings("serial") 25 | public static class MyVirtualPropertyWriter extends VirtualBeanPropertyWriter { 26 | protected MyVirtualPropertyWriter() { } 27 | 28 | protected MyVirtualPropertyWriter(BeanPropertyDefinition propDef, Annotations contextAnnotations, 29 | JavaType declaredType) { 30 | super(propDef, contextAnnotations, declaredType); 31 | } 32 | @Override 33 | protected Object value(Object bean, JsonGenerator g, SerializerProvider prov) throws Exception { 34 | return "bar"; 35 | } 36 | @Override 37 | public VirtualBeanPropertyWriter withConfig(MapperConfig config, AnnotatedClass declaringClass, 38 | BeanPropertyDefinition propDef, JavaType type) { 39 | return new MyVirtualPropertyWriter(propDef, declaringClass.getAnnotations(), type); 40 | } 41 | } 42 | 43 | public void testSimpleAppend() throws Exception 44 | { 45 | ObjectMapper mapper = mapperWithModule(); 46 | // ObjectMapper mapper = new ObjectMapper(); 47 | String json = mapper.writeValueAsString(new Pojo("foo")); 48 | assertEquals("{\"name\":\"foo\",\"virtual\":\"bar\"}", json); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/ser/SerializeWithViewTest.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | 6 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 7 | 8 | public class SerializeWithViewTest extends AfterburnerTestBase 9 | { 10 | @JsonPropertyOrder({ "a", "b" }) 11 | static class Bean { 12 | @JsonView({ String.class }) 13 | public int a; 14 | 15 | @JsonView({ Integer.class, Character.class }) 16 | public int b; 17 | } 18 | 19 | public void testWriterWithView() throws Exception 20 | { 21 | ObjectMapper mapper = mapperWithModule(); 22 | 23 | String json = mapper.writeValueAsString(new Bean()); 24 | // by default: both fields serialized 25 | assertEquals("{\"a\":0,\"b\":0}", json); 26 | 27 | // but with view enabled, just one 28 | json = mapper.writerWithView(Integer.class).writeValueAsString(new Bean()); 29 | assertEquals("{\"b\":0}", json); 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/ser/TestAccessorGeneration.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | import com.fasterxml.jackson.databind.PropertyName; 6 | import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; 7 | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; 8 | import com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition; 9 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 10 | 11 | public class TestAccessorGeneration extends AfterburnerTestBase 12 | { 13 | /* 14 | /********************************************************************** 15 | /* Helper types 16 | /********************************************************************** 17 | */ 18 | 19 | public static class Bean1 { 20 | public int getX() { return 13; } 21 | } 22 | 23 | public static class Bean3 { 24 | public int getX() { return 13; } 25 | public int getY() { return 27; } 26 | public int get3() { return 3; } 27 | } 28 | 29 | public static class BeanN { 30 | public int getX() { return 13; } 31 | public int getY() { return 27; } 32 | 33 | public int get3() { return 3; } 34 | public int get4() { return 4; } 35 | public int get5() { return 5; } 36 | public int get6() { return 6; } 37 | public int get7() { return 7; } 38 | } 39 | 40 | /* 41 | /********************************************************************** 42 | /* Test methods 43 | /********************************************************************** 44 | */ 45 | 46 | public void testSingleIntAccessorGeneration() throws Exception 47 | { 48 | Method method = Bean1.class.getDeclaredMethod("getX"); 49 | AnnotatedMethod annMethod = new AnnotatedMethod(null, method, null, null); 50 | PropertyAccessorCollector coll = new PropertyAccessorCollector(Bean1.class); 51 | BeanPropertyWriter bpw = new BeanPropertyWriter(SimpleBeanPropertyDefinition 52 | .construct(null, annMethod, new PropertyName("x")), 53 | annMethod, null, 54 | null, 55 | null, null, null, 56 | false, null); 57 | coll.addIntGetter(bpw); 58 | BeanPropertyAccessor acc = coll.findAccessor(null); 59 | Bean1 bean = new Bean1(); 60 | int value = acc.intGetter(bean, 0); 61 | assertEquals(bean.getX(), value); 62 | } 63 | 64 | public void testDualIntAccessorGeneration() throws Exception 65 | { 66 | PropertyAccessorCollector coll = new PropertyAccessorCollector(Bean3.class); 67 | 68 | String[] methodNames = new String[] { 69 | "getX", "getY", "get3" 70 | }; 71 | 72 | /* 73 | public BeanPropertyWriter(BeanPropertyDefinition propDef, 74 | AnnotatedMember member, Annotations contextAnnotations, 75 | JavaType declaredType, 76 | JsonSerializer ser, TypeSerializer typeSer, JavaType serType, 77 | boolean suppressNulls, Object suppressableValue) 78 | */ 79 | 80 | for (String methodName : methodNames) { 81 | Method method = Bean3.class.getDeclaredMethod(methodName); 82 | AnnotatedMethod annMethod = new AnnotatedMethod(null, method, null, null); 83 | // should we translate from method name to property name? 84 | coll.addIntGetter(new BeanPropertyWriter(SimpleBeanPropertyDefinition 85 | .construct(null, annMethod, new PropertyName(methodName)), 86 | annMethod, null, 87 | null, 88 | null, null, null, 89 | false, null)); 90 | } 91 | 92 | BeanPropertyAccessor acc = coll.findAccessor(null); 93 | Bean3 bean = new Bean3(); 94 | 95 | assertEquals(bean.getX(), acc.intGetter(bean, 0)); 96 | assertEquals(bean.getY(), acc.intGetter(bean, 1)); 97 | assertEquals(bean.get3(), acc.intGetter(bean, 2)); 98 | } 99 | 100 | // And then test to ensure Switch-table construction also works... 101 | public void testLotsaIntAccessorGeneration() throws Exception 102 | { 103 | PropertyAccessorCollector coll = new PropertyAccessorCollector(BeanN.class); 104 | String[] methodNames = new String[] { 105 | "getX", "getY", "get3", "get4", "get5", "get6", "get7" 106 | }; 107 | for (String methodName : methodNames) { 108 | Method method = BeanN.class.getDeclaredMethod(methodName); 109 | AnnotatedMethod annMethod = new AnnotatedMethod(null, method, null, null); 110 | coll.addIntGetter(new BeanPropertyWriter(SimpleBeanPropertyDefinition.construct( 111 | null, annMethod, new PropertyName(methodName)), 112 | annMethod, null, 113 | null, 114 | null, null, null, 115 | false, null)); 116 | } 117 | 118 | BeanPropertyAccessor acc = coll.findAccessor(null); 119 | BeanN bean = new BeanN(); 120 | 121 | assertEquals(bean.getX(), acc.intGetter(bean, 0)); 122 | assertEquals(bean.getY(), acc.intGetter(bean, 1)); 123 | 124 | assertEquals(bean.get3(), acc.intGetter(bean, 2)); 125 | assertEquals(bean.get4(), acc.intGetter(bean, 3)); 126 | assertEquals(bean.get5(), acc.intGetter(bean, 4)); 127 | assertEquals(bean.get6(), acc.intGetter(bean, 5)); 128 | assertEquals(bean.get7(), acc.intGetter(bean, 6)); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/ser/TestInclusionAnnotations.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | 7 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 8 | 9 | public class TestInclusionAnnotations extends AfterburnerTestBase 10 | { 11 | static class IntWrapper 12 | { 13 | @JsonInclude(JsonInclude.Include.NON_NULL) 14 | public Integer value; 15 | 16 | public IntWrapper(Integer v) { value = v; } 17 | } 18 | 19 | static class NonEmptyIntWrapper { 20 | private int value; 21 | public NonEmptyIntWrapper(int v) { value = v; } 22 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 23 | public int getValue() { return value; } 24 | } 25 | 26 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 27 | static class NonEmptyIntWrapper2 { 28 | public int value; 29 | public NonEmptyIntWrapper2(int v) { value = v; } 30 | } 31 | 32 | // But whereas 'empty' should NOT include '0', 'default' for property should 33 | static class NonDefaultIntWrapper { 34 | private int value; 35 | public NonDefaultIntWrapper(int v) { value = v; } 36 | @JsonInclude(JsonInclude.Include.NON_DEFAULT) 37 | public int getValue() { return value; } 38 | } 39 | 40 | public class NonEmptyStringWrapper { 41 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 42 | public String value; 43 | public NonEmptyStringWrapper(String v) { value = v; } 44 | } 45 | 46 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 47 | public class NonEmptyStringWrapper2 { 48 | public String value; 49 | public NonEmptyStringWrapper2(String v) { value = v; } 50 | } 51 | 52 | public class AnyWrapper 53 | { 54 | public String name = "Foo"; 55 | 56 | @JsonInclude(JsonInclude.Include.NON_NULL) 57 | public Object wrapped; 58 | 59 | public AnyWrapper(Object w) { wrapped = w; } 60 | } 61 | 62 | /* 63 | /********************************************************************** 64 | /* Test methods 65 | /********************************************************************** 66 | */ 67 | 68 | public void testIncludeUsingAnnotation() throws Exception 69 | { 70 | ObjectMapper mapper = mapperWithModule(); 71 | 72 | String json = mapper.writeValueAsString(new IntWrapper(3)); 73 | assertEquals("{\"value\":3}", json); 74 | json = mapper.writeValueAsString(new IntWrapper(null)); 75 | assertEquals("{}", json); 76 | 77 | json = mapper.writeValueAsString(new AnyWrapper(new IntWrapper(null))); 78 | assertEquals("{\"name\":\"Foo\",\"wrapped\":{}}", json); 79 | json = mapper.writeValueAsString(new AnyWrapper(null)); 80 | assertEquals("{\"name\":\"Foo\"}", json); 81 | } 82 | 83 | // [module-afterburner#39] 84 | public void testEmptyExclusion() throws Exception 85 | { 86 | ObjectMapper mapper = mapperWithModule(); 87 | String json; 88 | 89 | json = mapper.writeValueAsString(new NonEmptyIntWrapper(3)); 90 | assertEquals("{\"value\":3}", json); 91 | // as per [module-afterburner#63], ints should not have "empty" value 92 | // (temporarily, for 2.6, they did have) 93 | json = mapper.writeValueAsString(new NonEmptyIntWrapper(0)); 94 | assertEquals("{\"value\":0}", json); 95 | 96 | json = mapper.writeValueAsString(new NonEmptyStringWrapper("x")); 97 | assertEquals("{\"value\":\"x\"}", json); 98 | json = mapper.writeValueAsString(new NonEmptyStringWrapper("")); 99 | assertEquals("{}", json); 100 | json = mapper.writeValueAsString(new NonEmptyStringWrapper(null)); 101 | assertEquals("{}", json); 102 | } 103 | 104 | public void testEmptyExclusionViaClass() throws Exception 105 | { 106 | ObjectMapper mapper = mapperWithModule(); 107 | 108 | assertEquals("{\"value\":3}", 109 | mapper.writeValueAsString(new NonEmptyIntWrapper2(3))); 110 | assertEquals("{\"value\":0}", 111 | mapper.writeValueAsString(new NonEmptyIntWrapper2(0))); 112 | 113 | assertEquals("{\"value\":\"x\"}", 114 | mapper.writeValueAsString(new NonEmptyStringWrapper2("x"))); 115 | assertEquals("{}", 116 | mapper.writeValueAsString(new NonEmptyStringWrapper2(""))); 117 | assertEquals("{}", 118 | mapper.writeValueAsString(new NonEmptyStringWrapper2(null))); 119 | } 120 | 121 | public void testDefaultExclusion() throws Exception 122 | { 123 | ObjectMapper mapper = mapperWithModule(); 124 | String json; 125 | 126 | json = mapper.writeValueAsString(new NonDefaultIntWrapper(3)); 127 | assertEquals("{\"value\":3}", json); 128 | json = mapper.writeValueAsString(new NonDefaultIntWrapper(0)); 129 | assertEquals("{}", json); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/ser/TestInterfaceSerialize.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 5 | 6 | public class TestInterfaceSerialize extends AfterburnerTestBase 7 | { 8 | public interface Wat 9 | { 10 | String getFoo(); 11 | } 12 | 13 | public void testInterfaceSerialize() throws Exception 14 | { 15 | ObjectMapper mapper = mapperWithModule(); 16 | 17 | Wat wat = new Wat() { 18 | @Override 19 | public String getFoo() { 20 | return "bar"; 21 | } 22 | }; 23 | 24 | // Causes IncompatibleClassChangeError 25 | assertEquals("{\"foo\":\"bar\"}", mapper.writerFor(Wat.class).writeValueAsString(wat)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/ser/TestJsonFilter.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | import com.fasterxml.jackson.databind.*; 5 | import com.fasterxml.jackson.databind.ser.FilterProvider; 6 | import com.fasterxml.jackson.databind.ser.impl.*; 7 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 8 | 9 | /** 10 | * Tests for verifying that bean property filtering using JsonFilter 11 | * works as expected. 12 | */ 13 | public class TestJsonFilter extends AfterburnerTestBase 14 | { 15 | @JsonFilter("RootFilter") 16 | static class Bean { 17 | public String a = "a"; 18 | public String b = "b"; 19 | } 20 | 21 | 22 | // [Issue#89] 23 | static class Pod 24 | { 25 | protected String username; 26 | 27 | // @JsonProperty(value = "user_password") 28 | protected String userPassword; 29 | 30 | public String getUsername() { 31 | return username; 32 | } 33 | 34 | public void setUsername(String value) { 35 | this.username = value; 36 | } 37 | 38 | @JsonIgnore 39 | @JsonProperty(value = "user_password") 40 | public java.lang.String getUserPassword() { 41 | return userPassword; 42 | } 43 | 44 | @JsonProperty(value = "user_password") 45 | public void setUserPassword(String value) { 46 | this.userPassword = value; 47 | } 48 | } 49 | 50 | // [Issue#306]: JsonFilter for properties, too! 51 | 52 | @JsonPropertyOrder(alphabetic=true) 53 | static class FilteredProps 54 | { 55 | // will default to using "RootFilter", only including 'a' 56 | public Bean first = new Bean(); 57 | 58 | // but minimal includes 'b' 59 | @JsonFilter("b") 60 | public Bean second = new Bean(); 61 | } 62 | 63 | /* 64 | /********************************************************** 65 | /* Unit tests 66 | /********************************************************** 67 | */ 68 | 69 | private final ObjectMapper MAPPER = mapperWithModule(); 70 | 71 | public void testSimpleInclusionFilter() throws Exception 72 | { 73 | FilterProvider prov = new SimpleFilterProvider().addFilter("RootFilter", 74 | SimpleBeanPropertyFilter.filterOutAllExcept("a")); 75 | assertEquals("{\"a\":\"a\"}", MAPPER.writer(prov).writeValueAsString(new Bean())); 76 | 77 | // [JACKSON-504]: also verify it works via mapper 78 | ObjectMapper mapper = new ObjectMapper(); 79 | mapper.setFilterProvider(prov); 80 | assertEquals("{\"a\":\"a\"}", mapper.writeValueAsString(new Bean())); 81 | } 82 | 83 | public void testSimpleExclusionFilter() throws Exception 84 | { 85 | FilterProvider prov = new SimpleFilterProvider().addFilter("RootFilter", 86 | SimpleBeanPropertyFilter.serializeAllExcept("a")); 87 | assertEquals("{\"b\":\"b\"}", MAPPER.writer(prov).writeValueAsString(new Bean())); 88 | } 89 | 90 | // should handle missing case gracefully 91 | public void testMissingFilter() throws Exception 92 | { 93 | // First: default behavior should be to throw an exception 94 | try { 95 | MAPPER.writeValueAsString(new Bean()); 96 | fail("Should have failed without configured filter"); 97 | } catch (JsonMappingException e) { // should be resolved to a MappingException (internally may be something else) 98 | verifyException(e, "Can not resolve PropertyFilter with id 'RootFilter'"); 99 | } 100 | 101 | // but when changing behavior, should work difference 102 | SimpleFilterProvider fp = new SimpleFilterProvider().setFailOnUnknownId(false); 103 | ObjectMapper mapper = new ObjectMapper(); 104 | mapper.setFilterProvider(fp); 105 | String json = mapper.writeValueAsString(new Bean()); 106 | assertEquals("{\"a\":\"a\",\"b\":\"b\"}", json); 107 | } 108 | 109 | // defaulting, as per [JACKSON-449] 110 | public void testDefaultFilter() throws Exception 111 | { 112 | FilterProvider prov = new SimpleFilterProvider().setDefaultFilter(SimpleBeanPropertyFilter.filterOutAllExcept("b")); 113 | assertEquals("{\"b\":\"b\"}", MAPPER.writer(prov).writeValueAsString(new Bean())); 114 | } 115 | 116 | // [Issue#89] combining @JsonIgnore, @JsonProperty 117 | public void testIssue89() throws Exception 118 | { 119 | ObjectMapper mapper = new ObjectMapper(); 120 | Pod pod = new Pod(); 121 | pod.username = "Bob"; 122 | pod.userPassword = "s3cr3t!"; 123 | 124 | String json = mapper.writeValueAsString(pod); 125 | 126 | assertEquals("{\"username\":\"Bob\"}", json); 127 | 128 | Pod pod2 = mapper.readValue("{\"username\":\"Bill\",\"user_password\":\"foo!\"}", Pod.class); 129 | assertEquals("Bill", pod2.username); 130 | assertEquals("foo!", pod2.userPassword); 131 | } 132 | 133 | // Wrt [Issue#306] 134 | public void testFilterOnProperty() throws Exception 135 | { 136 | FilterProvider prov = new SimpleFilterProvider() 137 | .addFilter("RootFilter", SimpleBeanPropertyFilter.filterOutAllExcept("a")) 138 | .addFilter("b", SimpleBeanPropertyFilter.filterOutAllExcept("b")); 139 | 140 | assertEquals("{\"first\":{\"a\":\"a\"},\"second\":{\"b\":\"b\"}}", 141 | MAPPER.writer(prov).writeValueAsString(new FilteredProps())); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/ser/TestJsonSerializeAnnotationBug.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import com.fasterxml.jackson.annotation.JsonCreator; 6 | import com.fasterxml.jackson.annotation.JsonProperty; 7 | 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 10 | import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; 11 | 12 | public class TestJsonSerializeAnnotationBug 13 | extends com.fasterxml.jackson.module.afterburner.AfterburnerTestBase 14 | { 15 | public static class TestObjectWithJsonSerialize { 16 | @JsonSerialize(using = ToStringSerializer.class) 17 | private final BigDecimal amount; 18 | 19 | @JsonCreator 20 | public TestObjectWithJsonSerialize(@JsonProperty("amount") BigDecimal amount) { 21 | this.amount = amount; 22 | } 23 | 24 | @JsonSerialize(using = ToStringSerializer.class) @JsonProperty("amount") 25 | public BigDecimal getAmount() { 26 | return amount; 27 | } 28 | } 29 | 30 | public void testAfterburnerModule() throws Exception 31 | { 32 | ObjectMapper mapper = mapperWithModule(); 33 | 34 | String value = mapper.writeValueAsString(new TestObjectWithJsonSerialize(new BigDecimal("870.04"))); 35 | assertNotNull(value); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/ser/TestRawValues.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import com.fasterxml.jackson.annotation.JsonRawValue; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 6 | 7 | public class TestRawValues extends AfterburnerTestBase 8 | { 9 | static class SerializableObject 10 | { 11 | public SerializableObject(String v) { value = v; } 12 | 13 | @JsonRawValue 14 | public String value; 15 | } 16 | 17 | /* 18 | /********************************************************** 19 | /* Unit tests 20 | /********************************************************** 21 | */ 22 | 23 | private final ObjectMapper MAPPER = mapperWithModule(); 24 | 25 | public void testAfterBurner() throws Exception 26 | { 27 | SerializableObject so = new SerializableObject("[123]"); 28 | 29 | assertEquals("{\"value\":[123]}", MAPPER.writeValueAsString(so)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/ser/TestStdSerializerOverrides.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.ser; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.JsonGenerator; 6 | import com.fasterxml.jackson.core.Version; 7 | 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | import com.fasterxml.jackson.databind.SerializerProvider; 10 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 11 | import com.fasterxml.jackson.databind.module.SimpleModule; 12 | import com.fasterxml.jackson.databind.ser.std.StdSerializer; 13 | 14 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 15 | 16 | public class TestStdSerializerOverrides extends AfterburnerTestBase 17 | { 18 | static class ClassWithPropOverrides 19 | { 20 | public String a = "a"; 21 | 22 | @JsonSerialize(using=MyStringSerializer.class) 23 | public String b = "b"; 24 | } 25 | 26 | @SuppressWarnings("serial") 27 | static class MyStringSerializer extends StdSerializer 28 | { 29 | public MyStringSerializer() { super(String.class); } 30 | 31 | @Override 32 | public void serialize(String value, JsonGenerator gen, 33 | SerializerProvider provider) throws IOException { 34 | gen.writeString("Foo:"+value); 35 | } 36 | } 37 | 38 | // for [module-afterburner#59] 39 | static class FooBean { 40 | public String field = "value"; 41 | } 42 | 43 | /* 44 | /********************************************************************** 45 | /* Test methods 46 | /********************************************************************** 47 | */ 48 | 49 | public void testFiveMinuteDoc() throws Exception 50 | { 51 | ObjectMapper plainMapper = new ObjectMapper(); 52 | ObjectMapper abMapper = mapperWithModule(); 53 | ClassWithPropOverrides input = new ClassWithPropOverrides(); 54 | String jsonPlain = plainMapper.writeValueAsString(input); 55 | String jsonAb = abMapper.writeValueAsString(input); 56 | assertEquals(jsonPlain, jsonAb); 57 | } 58 | 59 | public void testStringSerOverideNoAfterburner() throws Exception 60 | { 61 | final FooBean input = new FooBean(); 62 | final String EXP = "{\"field\":\"Foo:value\"}"; 63 | String json = new ObjectMapper() 64 | .registerModule(new SimpleModule("module", Version.unknownVersion()) 65 | .addSerializer(String.class, new MyStringSerializer())) 66 | .writeValueAsString(input); 67 | assertEquals(EXP, json); 68 | } 69 | 70 | public void testStringSerOverideWithAfterburner() throws Exception 71 | { 72 | final FooBean input = new FooBean(); 73 | final String EXP = "{\"field\":\"Foo:value\"}"; 74 | String json = mapperWithModule() 75 | .registerModule(new SimpleModule("module", Version.unknownVersion()) 76 | .addSerializer(String.class, new MyStringSerializer())) 77 | .writeValueAsString(input); 78 | assertEquals(EXP, json); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/test/java/com/fasterxml/jackson/module/afterburner/util/MyClassLoaderTest.java: -------------------------------------------------------------------------------- 1 | package com.fasterxml.jackson.module.afterburner.util; 2 | 3 | import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; 4 | 5 | public class MyClassLoaderTest extends AfterburnerTestBase 6 | { 7 | public void testNameReplacement() throws Exception 8 | { 9 | byte[] input = "Something with FOO in it (but not just FO!): FOOFOO".getBytes("UTF-8"); 10 | int count = MyClassLoader.replaceName(input, "FOO", "BAR"); 11 | assertEquals(3, count); 12 | assertEquals("Something with BAR in it (but not just FO!): BARBAR", new String(input, "UTF-8")); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/perf/MediaItem.java: -------------------------------------------------------------------------------- 1 | package perf; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class MediaItem 7 | { 8 | public Media media; 9 | public List images; 10 | 11 | public MediaItem() { } 12 | 13 | public MediaItem addPhoto(Image i) { 14 | if (images == null) { 15 | images = new ArrayList(); 16 | } 17 | images.add(i); 18 | return this; 19 | } 20 | 21 | static MediaItem buildItem() 22 | { 23 | Media content = new Media(); 24 | content.player = Player.JAVA; 25 | content.uri = "http://javaone.com/keynote.mpg"; 26 | content.title = "Javaone Keynote"; 27 | content.width = 640; 28 | content.height = 480; 29 | content.format = "video/mpeg4"; 30 | content.duration = 18000000L; 31 | content.size = 58982400L; 32 | content.bitrate = 262144; 33 | content.copyright = "None"; 34 | content.addPerson("Bill Gates"); 35 | content.addPerson("Steve Jobs"); 36 | 37 | MediaItem item = new MediaItem(); 38 | item.media = content; 39 | 40 | item.addPhoto(new Image("http://javaone.com/keynote_large.jpg", "Javaone Keynote", 1024, 768, Size.LARGE)); 41 | item.addPhoto(new Image("http://javaone.com/keynote_small.jpg", "Javaone Keynote", 320, 240, Size.SMALL)); 42 | 43 | return item; 44 | } 45 | } 46 | 47 | enum Size { SMALL, LARGE }; 48 | 49 | class Image 50 | { 51 | public Image() { } 52 | public Image(String uri, String title, int w, int h, Size s) { 53 | this.uri = uri; 54 | this.title = title; 55 | width = w; 56 | height = h; 57 | size = s; 58 | } 59 | 60 | public String uri; 61 | public String title; 62 | public int width, height; 63 | public Size size; 64 | } 65 | 66 | enum Player { JAVA, FLASH; } 67 | 68 | class Media { 69 | 70 | public String uri; 71 | public String title; // Can be unset. 72 | public int width; 73 | public int height; 74 | public String format; 75 | public long duration; 76 | public long size; 77 | public int bitrate; // Can be unset. 78 | // public boolean hasBitrate; 79 | 80 | public List persons; 81 | 82 | public Player player; 83 | 84 | public String copyright; // Can be unset. 85 | 86 | public Media addPerson(String p) { 87 | if (persons == null) { 88 | persons = new ArrayList(); 89 | } 90 | persons.add(p); 91 | return this; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/test/java/perf/NopOutputStream.java: -------------------------------------------------------------------------------- 1 | package perf; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | 6 | class NopOutputStream extends OutputStream 7 | { 8 | public NopOutputStream() { } 9 | 10 | @Override 11 | public void write(int b) throws IOException { } 12 | 13 | @Override 14 | public void write(byte[] b) throws IOException { } 15 | 16 | @Override 17 | public void write(byte[] b, int offset, int len) throws IOException { } 18 | } -------------------------------------------------------------------------------- /src/test/java/perf/TestPojo.java: -------------------------------------------------------------------------------- 1 | package perf; 2 | 3 | class TestPojo 4 | { 5 | public int a = 1, b; 6 | public String name = "Something"; 7 | public Value value1, value2; 8 | 9 | public TestPojo() { } 10 | public TestPojo(int a, int b, 11 | String name, Value v) { 12 | this.a = a; 13 | this.b = b; 14 | this.name = name; 15 | this.value1 = v; 16 | this.value2 = v; 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/java/perf/Value.java: -------------------------------------------------------------------------------- 1 | package perf; 2 | 3 | class Value { 4 | public int x, y; 5 | 6 | public Value() { } 7 | public Value(int x, int y) { 8 | this.x = x; 9 | this.y = y; 10 | } 11 | } -------------------------------------------------------------------------------- /src/test/java/perftest/TestDeserializePerf.java: -------------------------------------------------------------------------------- 1 | package perftest; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.JsonFactory; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | 8 | import com.fasterxml.jackson.module.afterburner.AfterburnerModule; 9 | 10 | public class TestDeserializePerf 11 | { 12 | public final static class Bean 13 | { 14 | public int a, b, c123, d; 15 | public int e, foobar, g, habitus; 16 | 17 | public Bean setUp() { 18 | a = 1; 19 | b = 999; 20 | c123 = -1000; 21 | d = 13; 22 | e = 6; 23 | foobar = -33; 24 | g = 0; 25 | habitus = 123456789; 26 | return this; 27 | } 28 | 29 | public void setA(int v) { a = v; } 30 | public void setB(int v) { b = v; } 31 | public void setC(int v) { c123 = v; } 32 | public void setD(int v) { d = v; } 33 | 34 | public void setE(int v) { e = v; } 35 | public void setF(int v) { foobar = v; } 36 | public void setG(int v) { g = v; } 37 | public void setH(int v) { habitus = v; } 38 | 39 | @Override 40 | public int hashCode() { 41 | return a + b + c123 + d + e + foobar + g + habitus; 42 | } 43 | } 44 | 45 | public static void main(String[] args) throws Exception 46 | { 47 | // JsonFactory f = new org.codehaus.jackson.smile.SmileFactory(); 48 | JsonFactory f = new JsonFactory(); 49 | ObjectMapper mapperSlow = new ObjectMapper(f); 50 | ObjectMapper mapperFast = new ObjectMapper(f); 51 | 52 | // !!! TEST -- to get profile info, comment out: 53 | // mapperSlow.registerModule(new AfterburnerModule()); 54 | 55 | mapperFast.registerModule(new AfterburnerModule()); 56 | new TestDeserializePerf().testWith(mapperSlow, mapperFast); 57 | } 58 | 59 | private void testWith(ObjectMapper slowMapper, ObjectMapper fastMapper) 60 | throws IOException 61 | { 62 | byte[] json = slowMapper.writeValueAsBytes(new Bean().setUp()); 63 | boolean fast = true; 64 | 65 | while (true) { 66 | long now = System.currentTimeMillis(); 67 | 68 | ObjectMapper m = fast ? fastMapper : slowMapper; 69 | Bean bean = null; 70 | 71 | for (int i = 0; i < 199999; ++i) { 72 | bean = m.readValue(json, Bean.class); 73 | } 74 | long time = System.currentTimeMillis() - now; 75 | 76 | System.out.println("Mapper (fast: "+fast+"; "+bean.hashCode()+"); took "+time+" msecs"); 77 | 78 | fast = !fast; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/perftest/TestJvmDeserPerf.java: -------------------------------------------------------------------------------- 1 | package perftest; 2 | 3 | import com.fasterxml.jackson.core.JsonFactory; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.databind.JavaType; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.fasterxml.jackson.databind.type.TypeFactory; 8 | 9 | /** 10 | * Micro-benchmark for comparing performance of bean deserialization 11 | */ 12 | public final class TestJvmDeserPerf 13 | { 14 | /* 15 | /********************************************************** 16 | /* Actual test 17 | /********************************************************** 18 | */ 19 | 20 | private final int REPS; 21 | 22 | private TestJvmDeserPerf() { 23 | // Let's try to guestimate suitable size 24 | REPS = 35000; 25 | } 26 | 27 | private MediaItem buildItem() 28 | { 29 | MediaItem.Content content = new MediaItem.Content(); 30 | content.setPlayer(MediaItem.Content.Player.JAVA); 31 | content.setUri("http://javaone.com/keynote.mpg"); 32 | content.setTitle("Javaone Keynote"); 33 | content.setWidth(640); 34 | content.setHeight(480); 35 | content.setFormat("video/mpeg4"); 36 | content.setDuration(18000000L); 37 | content.setSize(58982400L); 38 | content.setBitrate(262144); 39 | content.setCopyright("None"); 40 | content.addPerson("Bill Gates"); 41 | content.addPerson("Steve Jobs"); 42 | 43 | MediaItem item = new MediaItem(content); 44 | 45 | item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_large.jpg", "Javaone Keynote", 1024, 768, MediaItem.Photo.Size.LARGE)); 46 | item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_small.jpg", "Javaone Keynote", 320, 240, MediaItem.Photo.Size.SMALL)); 47 | 48 | return item; 49 | } 50 | 51 | public void test() 52 | throws Exception 53 | { 54 | int sum = 0; 55 | 56 | final MediaItem item = buildItem(); 57 | JsonFactory jsonF = 58 | // new org.codehaus.jackson.smile.SmileFactory(); 59 | new JsonFactory() 60 | ; 61 | 62 | final ObjectMapper jsonMapper = new ObjectMapper(jsonF); 63 | jsonMapper.registerModule(new com.fasterxml.jackson.module.afterburner.AfterburnerModule()); 64 | 65 | byte[] json = jsonMapper.writeValueAsBytes(item); 66 | System.out.println("Warmed up: data size is "+json.length+" bytes; "+REPS+" reps -> " 67 | +((REPS * json.length) >> 10)+" kB per iteration"); 68 | System.out.println(); 69 | 70 | int round = 0; 71 | while (true) { 72 | // try { Thread.sleep(100L); } catch (InterruptedException ie) { } 73 | 74 | round = (round + 1) % 2; 75 | long curr = System.currentTimeMillis(); 76 | String msg; 77 | boolean lf = (round == 0); 78 | 79 | switch (round) { 80 | 81 | case 0: 82 | msg = "Deserialize/databind, JSON"; 83 | sum += testDeser(jsonMapper, json, REPS); 84 | break; 85 | 86 | case 1: 87 | msg = "Deserialize/manual, JSON"; 88 | sum += testDeser(jsonMapper.getFactory(), json, REPS); 89 | break; 90 | 91 | default: 92 | throw new Error("Internal error"); 93 | } 94 | 95 | curr = System.currentTimeMillis() - curr; 96 | if (lf) { 97 | System.out.println(); 98 | } 99 | System.out.println("Test '"+msg+"' -> "+curr+" msecs (" 100 | +(sum & 0xFF)+")."); 101 | } 102 | } 103 | 104 | protected int testDeser(ObjectMapper mapper, byte[] input, int reps) 105 | throws Exception 106 | { 107 | JavaType type = TypeFactory.defaultInstance().constructType(MediaItem.class); 108 | MediaItem item = null; 109 | for (int i = 0; i < reps; ++i) { 110 | item = mapper.readValue(input, 0, input.length, type); 111 | } 112 | return item.hashCode(); // just to get some non-optimizable number 113 | } 114 | 115 | protected int testDeser(JsonFactory jf, byte[] input, int reps) 116 | throws Exception 117 | { 118 | MediaItem item = null; 119 | for (int i = 0; i < reps; ++i) { 120 | JsonParser jp = jf.createParser(input); 121 | item = MediaItem.deserialize(jp); 122 | jp.close(); 123 | } 124 | return item.hashCode(); // just to get some non-optimizable number 125 | } 126 | 127 | public static void main(String[] args) throws Exception 128 | { 129 | new TestJvmDeserPerf().test(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/test/java/perftest/TestJvmSerPerf.java: -------------------------------------------------------------------------------- 1 | package perftest; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | 5 | import com.fasterxml.jackson.core.*; 6 | 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | 9 | import com.fasterxml.jackson.module.afterburner.AfterburnerModule; 10 | 11 | public final class TestJvmSerPerf 12 | { 13 | /* 14 | /********************************************************** 15 | /* Actual test 16 | /********************************************************** 17 | */ 18 | 19 | private final int REPS; 20 | 21 | private TestJvmSerPerf() throws Exception 22 | { 23 | // Let's try to guestimate suitable size... 24 | REPS = 20000; 25 | } 26 | 27 | private MediaItem buildItem() 28 | { 29 | MediaItem.Content content = new MediaItem.Content(); 30 | content.setPlayer(MediaItem.Content.Player.JAVA); 31 | content.setUri("http://javaone.com/keynote.mpg"); 32 | content.setTitle("Javaone Keynote"); 33 | content.setWidth(640); 34 | content.setHeight(480); 35 | content.setFormat("video/mpeg4"); 36 | content.setDuration(18000000L); 37 | content.setSize(58982400L); 38 | content.setBitrate(262144); 39 | content.setCopyright("None"); 40 | content.addPerson("Bill Gates"); 41 | content.addPerson("Steve Jobs"); 42 | 43 | MediaItem item = new MediaItem(content); 44 | 45 | item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_large.jpg", "Javaone Keynote", 1024, 768, MediaItem.Photo.Size.LARGE)); 46 | item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_small.jpg", "Javaone Keynote", 320, 240, MediaItem.Photo.Size.SMALL)); 47 | 48 | return item; 49 | } 50 | 51 | public void test() 52 | throws Exception 53 | { 54 | int i = 0; 55 | int sum = 0; 56 | 57 | ByteArrayOutputStream result = new ByteArrayOutputStream(); 58 | 59 | final MediaItem item = buildItem(); 60 | final JsonFactory jsonF = 61 | new JsonFactory() 62 | // new org.codehaus.jackson.smile.SmileFactory(); 63 | ; 64 | // ((SmileFactory) jsonF).configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, false); 65 | 66 | final ObjectMapper jsonMapper = new ObjectMapper(jsonF); 67 | jsonMapper.registerModule(new AfterburnerModule()); 68 | 69 | // jsonMapper.configure(SerializationConfig.Feature.USE_STATIC_TYPING, true); 70 | 71 | /* 72 | final SmileFactory smileFactory = new SmileFactory(); 73 | smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, true); 74 | smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, false); 75 | final ObjectMapper smileMapper = new ObjectMapper(smileFactory); 76 | */ 77 | 78 | while (true) { 79 | // Thread.sleep(150L); 80 | ++i; 81 | int round = (i % 2); 82 | 83 | // override? 84 | // round = 0; 85 | 86 | long curr = System.currentTimeMillis(); 87 | String msg; 88 | 89 | switch (round) { 90 | 91 | case 0: 92 | msg = "Serialize, JSON/databind"; 93 | sum += testObjectSer(jsonMapper, item, REPS+REPS, result); 94 | break; 95 | 96 | case 1: 97 | msg = "Serialize, JSON/manual"; 98 | sum += testObjectSer(jsonMapper.getFactory(), item, REPS+REPS, result); 99 | break; 100 | 101 | /* 102 | case 2: 103 | msg = "Serialize, Smile"; 104 | sum += testObjectSer(smileMapper, item, REPS, result); 105 | break; 106 | 107 | case 3: 108 | msg = "Serialize, Smile/manual"; 109 | sum += testObjectSer(smileFactory, item, REPS+REPS, result); 110 | break; 111 | */ 112 | 113 | default: 114 | throw new Error("Internal error"); 115 | } 116 | 117 | curr = System.currentTimeMillis() - curr; 118 | // if (round == 0) { System.out.println(); } 119 | System.out.println("Test '"+msg+"' -> "+curr+" msecs ("+(sum & 0xFF)+")."); 120 | if ((i & 0x1F) == 0) { // GC every 64 rounds 121 | System.out.println("[GC]"); 122 | Thread.sleep(20L); 123 | System.gc(); 124 | Thread.sleep(20L); 125 | } 126 | } 127 | } 128 | 129 | protected int testObjectSer(ObjectMapper mapper, Object value, int reps, ByteArrayOutputStream result) 130 | throws Exception 131 | { 132 | for (int i = 0; i < reps; ++i) { 133 | result.reset(); 134 | mapper.writeValue(result, value); 135 | } 136 | return result.size(); // just to get some non-optimizable number 137 | } 138 | 139 | protected int testObjectSer(JsonFactory jf, MediaItem value, int reps, ByteArrayOutputStream result) 140 | throws Exception 141 | { 142 | for (int i = 0; i < reps; ++i) { 143 | result.reset(); 144 | JsonGenerator jgen = jf.createGenerator(result, JsonEncoding.UTF8); 145 | value.serialize(jgen); 146 | jgen.close(); 147 | } 148 | return result.size(); // just to get some non-optimizable number 149 | } 150 | 151 | public static void main(String[] args) throws Exception 152 | { 153 | new TestJvmSerPerf().test(); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/test/java/perftest/TestSerializePerf.java: -------------------------------------------------------------------------------- 1 | package perftest; 2 | 3 | import java.io.*; 4 | 5 | import com.fasterxml.jackson.core.JsonFactory; 6 | 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | 9 | import com.fasterxml.jackson.module.afterburner.AfterburnerModule; 10 | 11 | public class TestSerializePerf 12 | { 13 | public final static class IntBean 14 | { 15 | public int getA() { return 37; } 16 | public int getBaobab() { return -123; } 17 | public int getC() { return 0; } 18 | public int getDonkey() { return 999999; } 19 | 20 | public int getE() { return 1; } 21 | public int getFoobar() { return 21; } 22 | public int getG() { return 345; } 23 | public int getHibernate() { return 99; } 24 | } 25 | 26 | public static void main(String[] args) throws Exception 27 | { 28 | // JsonFactory f = new org.codehaus.jackson.smile.SmileFactory(); 29 | JsonFactory f = new JsonFactory(); 30 | ObjectMapper mapperSlow = new ObjectMapper(f); 31 | ObjectMapper mapperFast = new ObjectMapper(f); 32 | 33 | // !!! TEST -- to get profile info, comment out: 34 | mapperSlow.registerModule(new AfterburnerModule()); 35 | 36 | mapperFast.registerModule(new AfterburnerModule()); 37 | new TestSerializePerf().testWith(mapperSlow, mapperFast); 38 | } 39 | 40 | private void testWith(ObjectMapper slowMapper, ObjectMapper fastMapper) 41 | throws IOException 42 | { 43 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 44 | boolean fast = true; 45 | final IntBean bean = new IntBean(); 46 | 47 | while (true) { 48 | long now = System.currentTimeMillis(); 49 | 50 | ObjectMapper m = fast ? fastMapper : slowMapper; 51 | int len = 0; 52 | 53 | for (int i = 0; i < 399999; ++i) { 54 | out.reset(); 55 | m.writeValue(out, bean); 56 | len = out.size(); 57 | } 58 | long time = System.currentTimeMillis() - now; 59 | 60 | System.out.println("Mapper (fast: "+fast+"; "+len+"); took "+time+" msecs"); 61 | 62 | fast = !fast; 63 | } 64 | } 65 | 66 | } 67 | --------------------------------------------------------------------------------