├── .jitpack.yml ├── sample ├── src │ ├── test │ │ ├── resources │ │ │ ├── MandatoryTestJson.json │ │ │ ├── DataClassJson_missing_values.json │ │ │ ├── DataClassJson_all_values.json │ │ │ ├── SealedClassSample_SingleType.json │ │ │ ├── InterfaceEqualityVariant1TestJson.json │ │ │ ├── InterfaceEqualityVariant2TestJson.json │ │ │ ├── Polymorphism_type_is_null.json │ │ │ ├── SealedClassSample.json │ │ │ ├── Polymorphism_valid.json │ │ │ ├── BookJson.json │ │ │ └── GsonErrorTestJson.json │ │ └── java │ │ │ └── gsonpath │ │ │ ├── adapter │ │ │ ├── standard │ │ │ │ └── extension │ │ │ │ │ └── invalid │ │ │ │ │ └── InvalidTests.kt │ │ │ └── enums │ │ │ │ └── EnumExampleTests.kt │ │ │ ├── generated │ │ │ └── StoreModelTest.java │ │ │ ├── TestUtil.kt │ │ │ ├── mandatory │ │ │ └── MandatoryFieldTest.java │ │ │ ├── array │ │ │ └── ArrayExampleTest.java │ │ │ └── kotlin │ │ │ └── DataClassSampleTest.java │ └── main │ │ └── java │ │ ├── gsonpath │ │ ├── mandatory │ │ │ └── MandatorySampleModel.java │ │ ├── TestGsonTypeFactory.java │ │ ├── adapter │ │ │ ├── subType │ │ │ │ ├── TypesList.java │ │ │ │ ├── TypesPojo.java │ │ │ │ └── Type.java │ │ │ ├── standard │ │ │ │ └── extension │ │ │ │ │ ├── flatten │ │ │ │ │ └── FlattenModel.java │ │ │ │ │ ├── range │ │ │ │ │ ├── intrange │ │ │ │ │ │ └── IntRangeModel.java │ │ │ │ │ └── floatrange │ │ │ │ │ │ └── FloatRangeModel.java │ │ │ │ │ └── invalid │ │ │ │ │ └── InvalidModel.kt │ │ │ └── enums │ │ │ │ └── EnumExample.kt │ │ ├── Nullable.java │ │ ├── NonNull.java │ │ ├── kotlin │ │ │ ├── CustomAnnotation.kt │ │ │ └── DataClassSample.kt │ │ ├── vanilla │ │ │ └── PeopleModelVanilla.java │ │ ├── generated │ │ │ ├── PersonModelGenerated.java │ │ │ └── StoreModel.java │ │ ├── array │ │ │ └── ArrayExample.java │ │ ├── errors │ │ │ └── GsonErrorTestModel.java │ │ └── interface_test │ │ │ └── InterfaceExample.java │ │ └── android │ │ └── support │ │ └── annotation │ │ ├── IntRange.java │ │ ├── Size.java │ │ └── FloatRange.java └── build.gradle ├── library ├── src │ ├── test │ │ ├── resources │ │ │ └── sample.json │ │ └── java │ │ │ └── gsonpath │ │ │ └── safe │ │ │ └── GsonSafeListTest.java │ └── main │ │ └── java │ │ └── gsonpath │ │ ├── exception │ │ ├── JsonFieldMissingException.java │ │ ├── JsonFieldNullException.java │ │ ├── JsonFieldNoKeyException.java │ │ └── JsonUnexpectedEnumValueException.java │ │ ├── annotation │ │ ├── GsonSubtypeGetter.java │ │ ├── ExcludeField.java │ │ ├── GsonPathGenerated.java │ │ ├── GsonSubtype.java │ │ ├── NestedJson.java │ │ ├── EnumGsonAdapter.java │ │ └── PathSubstitution.java │ │ ├── GsonSafeList.java │ │ ├── extension │ │ └── annotation │ │ │ ├── RemoveInvalidElements.java │ │ │ ├── EmptyToNull.java │ │ │ ├── IntRange.java │ │ │ ├── FlattenJson.java │ │ │ ├── Size.java │ │ │ └── FloatRange.java │ │ ├── GsonPathTypeAdapterFactory.java │ │ ├── GsonFieldValidationType.java │ │ ├── audit │ │ └── AuditJsonReader.java │ │ ├── internal │ │ ├── GsonPathTypeAdapter.java │ │ └── GsonUtil.java │ │ └── GsonPath.java ├── gradle.properties └── build.gradle ├── library-kt ├── src │ ├── test │ │ ├── resources │ │ │ └── sample.json │ │ └── java │ │ │ └── gsonpath │ │ │ └── result │ │ │ └── GsonResultListTest.kt │ └── main │ │ └── java │ │ └── gsonpath │ │ ├── GsonResult.kt │ │ ├── GsonResultList.kt │ │ └── GsonPathTypeAdapterFactoryKt.kt ├── gradle.properties └── build.gradle ├── compiler ├── standard │ ├── src │ │ ├── test │ │ │ ├── resources │ │ │ │ ├── mockito-extensions │ │ │ │ │ └── org.mockito.plugins.MockMaker │ │ │ │ └── generator │ │ │ │ │ ├── factory │ │ │ │ │ ├── NonGsonPathFile.java │ │ │ │ │ ├── TestLoaderSource.java │ │ │ │ │ ├── source2 │ │ │ │ │ │ ├── TestLoaderSource.java │ │ │ │ │ │ ├── TestLoaderSource2.java │ │ │ │ │ │ └── PackagePrivateTypeAdapterLoader.java │ │ │ │ │ ├── TestGsonTypeFactoryAsClass.java │ │ │ │ │ ├── TestGsonTypeFactoryNoInterfaces.java │ │ │ │ │ ├── source3 │ │ │ │ │ │ ├── TestLoaderSource.java │ │ │ │ │ │ └── PackagePrivateTypeAdapterLoader.java │ │ │ │ │ ├── TestGsonTypeFactoryIncorrectInterfaces.java │ │ │ │ │ ├── TestGsonTypeFactory.java │ │ │ │ │ ├── TestGsonTypeFactory2.java │ │ │ │ │ ├── PackagePrivateTypeAdapterLoader.java │ │ │ │ │ └── TestGsonTypeFactoryImpl.java │ │ │ │ │ ├── standard │ │ │ │ │ ├── generics │ │ │ │ │ │ ├── classes │ │ │ │ │ │ │ ├── IntermediateTest.java │ │ │ │ │ │ │ ├── GenericsTest.java │ │ │ │ │ │ │ └── BaseTest.java │ │ │ │ │ │ ├── interfaces │ │ │ │ │ │ │ ├── IntermediateTest.java │ │ │ │ │ │ │ ├── GenericsTest.java │ │ │ │ │ │ │ └── BaseTest.java │ │ │ │ │ │ └── interfaces_and_classs │ │ │ │ │ │ │ ├── BaseTest.java │ │ │ │ │ │ │ ├── GenericsTest.java │ │ │ │ │ │ │ └── IntermediateTest.java │ │ │ │ │ ├── empty │ │ │ │ │ │ ├── annotation_only │ │ │ │ │ │ │ ├── TestAnnotationOnly.java │ │ │ │ │ │ │ └── TestAnnotationOnly_GsonTypeAdapter.java │ │ │ │ │ │ ├── invalid_fields │ │ │ │ │ │ │ ├── TestInvalidFields.java │ │ │ │ │ │ │ └── TestInvalidFields_GsonTypeAdapter.java │ │ │ │ │ │ └── ignored_fields │ │ │ │ │ │ │ ├── TestIgnoredFields.java │ │ │ │ │ │ │ └── TestIgnoredFields_GsonTypeAdapter.java │ │ │ │ │ ├── inheritance │ │ │ │ │ │ ├── TestInheritance.java │ │ │ │ │ │ ├── TestInheritanceBase.java │ │ │ │ │ │ └── TestInheritance_GsonTypeAdapter.java │ │ │ │ │ ├── custom_serialized_name_annotation │ │ │ │ │ │ ├── GsonNest.java │ │ │ │ │ │ └── TestCustomSerializedNameModel.java │ │ │ │ │ ├── field_types │ │ │ │ │ │ ├── generics │ │ │ │ │ │ │ └── TestGenerics.java │ │ │ │ │ │ ├── custom_field │ │ │ │ │ │ │ └── TestCustomField.java │ │ │ │ │ │ ├── primitives │ │ │ │ │ │ │ └── valid │ │ │ │ │ │ │ │ └── TestValidPrimitives.java │ │ │ │ │ │ └── boxed_primitives │ │ │ │ │ │ │ └── TestBoxedPrimitives.java │ │ │ │ │ ├── TestGsonTypeFactory.java │ │ │ │ │ ├── nested_json │ │ │ │ │ │ ├── root_nesting │ │ │ │ │ │ │ └── TestRootNesting.java │ │ │ │ │ │ ├── field_nesting_autocomplete_inheritance │ │ │ │ │ │ │ ├── TestFieldNestingAutocompleteBase.java │ │ │ │ │ │ │ └── TestFieldNestingAutocomplete.java │ │ │ │ │ │ ├── field_nesting_autocomplete │ │ │ │ │ │ │ └── TestFieldNestingAutocomplete.java │ │ │ │ │ │ └── field_nesting │ │ │ │ │ │ │ └── TestFieldNesting.java │ │ │ │ │ ├── nested_class │ │ │ │ │ │ ├── TestNestedClass.java │ │ │ │ │ │ └── TestNestedClass_Nested_GsonTypeAdapter.java │ │ │ │ │ ├── field_annotations │ │ │ │ │ │ └── exclude │ │ │ │ │ │ │ ├── TestExclude.java │ │ │ │ │ │ │ └── TestExclude_GsonTypeAdapter.java │ │ │ │ │ ├── substitution │ │ │ │ │ │ ├── valid │ │ │ │ │ │ │ ├── TestSubstitutionBase.java │ │ │ │ │ │ │ ├── TestSubstitutionImpl1.java │ │ │ │ │ │ │ └── TestSubstitutionImpl2.java │ │ │ │ │ │ └── errors │ │ │ │ │ │ │ └── TestSubstitutionError_DuplicateKeys.java │ │ │ │ │ ├── delimiter │ │ │ │ │ │ ├── standard │ │ │ │ │ │ │ └── TestStandardDelimiter.java │ │ │ │ │ │ ├── custom │ │ │ │ │ │ │ └── TestCustomDelimiter.java │ │ │ │ │ │ └── multiple │ │ │ │ │ │ │ └── TestMultipleDelimiters.java │ │ │ │ │ ├── naming_policy │ │ │ │ │ │ ├── identity │ │ │ │ │ │ │ ├── TestNamePolicyIdentity.java │ │ │ │ │ │ │ └── TestNamePolicyIdentity_GsonTypeAdapter.java │ │ │ │ │ │ ├── upper_camel_case │ │ │ │ │ │ │ └── TestNamePolicyUpperCamelCase.java │ │ │ │ │ │ ├── lowercase_dashes │ │ │ │ │ │ │ └── TestNamePolicyLowerCaseDashes.java │ │ │ │ │ │ ├── lowercase_underscores │ │ │ │ │ │ │ └── TestNamePolicyLowerCaseUnderscores.java │ │ │ │ │ │ └── upper_camel_case_spaces │ │ │ │ │ │ │ └── TestNamePolicyUpperCamelCaseSpaces.java │ │ │ │ │ ├── processor_errors │ │ │ │ │ │ ├── TestInvalidFlattenJsonError.java │ │ │ │ │ │ ├── TestInvalidFieldTypeError.java │ │ │ │ │ │ ├── TestSerializedNameAlternateUsedError.java │ │ │ │ │ │ ├── TestDuplicateFieldError.java │ │ │ │ │ │ └── TestInvalidFieldPathError.java │ │ │ │ │ ├── custom_adapter_annotation │ │ │ │ │ │ ├── TestCustomAutoGsonAdapterModel.java │ │ │ │ │ │ └── CustomAutoGsonAdapter.java │ │ │ │ │ ├── serialize_nulls │ │ │ │ │ │ └── TestSerializeNulls.java │ │ │ │ │ ├── field_policy │ │ │ │ │ │ ├── default_value │ │ │ │ │ │ │ └── TestValidateWithDefaultValue.java │ │ │ │ │ │ ├── validate_all_except_nullable │ │ │ │ │ │ │ └── TestValidateAllExceptNullable.java │ │ │ │ │ │ ├── validate_explicit_non_null │ │ │ │ │ │ │ └── TestValidateExplicitNonNull.java │ │ │ │ │ │ └── no_validation │ │ │ │ │ │ │ └── TestNoValidation.java │ │ │ │ │ ├── array │ │ │ │ │ │ └── TestArray.java │ │ │ │ │ ├── use_getter_annotation │ │ │ │ │ │ └── UseGetterAnnotationTest.java │ │ │ │ │ └── using_constructor │ │ │ │ │ │ └── valid │ │ │ │ │ │ └── ValidConstructorTest.java │ │ │ │ │ ├── gson_sub_type │ │ │ │ │ ├── failures │ │ │ │ │ │ ├── TypesList_NoKeys.java │ │ │ │ │ │ ├── TypesList_NoGsonSubtypeGetter.java │ │ │ │ │ │ ├── TypesList_BlankFieldName.java │ │ │ │ │ │ ├── TypesList_DuplicateKeys.java │ │ │ │ │ │ ├── TypesList_IncorrectReturnType.java │ │ │ │ │ │ ├── TypesList_KeysAndParameterMismatch.java │ │ │ │ │ │ └── TypesList_TooManyGsonSubtypeGetters.java │ │ │ │ │ ├── indirectly_annotated │ │ │ │ │ │ ├── IndirectSubType.java │ │ │ │ │ │ └── IndirectlyAnnotatedSubType.java │ │ │ │ │ ├── one_argument │ │ │ │ │ │ ├── TypeGsonSubType.java │ │ │ │ │ │ └── TypeGsonSubType_GsonTypeAdapter.java │ │ │ │ │ └── two_arguments │ │ │ │ │ │ └── TypeGsonSubType.java │ │ │ │ │ ├── interf │ │ │ │ │ ├── invalid │ │ │ │ │ │ ├── TestValidInterface_ReturningVoid.java │ │ │ │ │ │ └── TestValidInterface_WithParameters.java │ │ │ │ │ ├── inheritance │ │ │ │ │ │ ├── TestUsingInheritanceBase.java │ │ │ │ │ │ └── TestUsingInheritance.java │ │ │ │ │ ├── java8 │ │ │ │ │ │ ├── TestJava8Interface.java │ │ │ │ │ │ ├── TestJava8Interface_GsonPathModel.java │ │ │ │ │ │ └── TestJava8Interface_GsonTypeAdapter.java │ │ │ │ │ ├── primitive │ │ │ │ │ │ └── TestUsingPrimitives.java │ │ │ │ │ └── valid │ │ │ │ │ │ ├── TestValidInterface.java │ │ │ │ │ │ └── PackagePrivateTypeAdapterLoader.java │ │ │ │ │ ├── extension │ │ │ │ │ ├── size │ │ │ │ │ │ └── valid │ │ │ │ │ │ │ ├── mutable │ │ │ │ │ │ │ └── TestMutableSize.java │ │ │ │ │ │ │ └── immutable │ │ │ │ │ │ │ └── TestImmutableSize.java │ │ │ │ │ └── invalid │ │ │ │ │ │ ├── mutable │ │ │ │ │ │ └── TestMutableRemoveInvalidElements.java │ │ │ │ │ │ └── immutable │ │ │ │ │ │ └── TestImmutableRemoveInvalidElements.java │ │ │ │ │ └── enums │ │ │ │ │ ├── with_default │ │ │ │ │ └── TestEnumWithDefault.java │ │ │ │ │ └── without_default │ │ │ │ │ └── TestEnumWithoutDefault.java │ │ │ └── java │ │ │ │ └── gsonpath │ │ │ │ ├── Nullable.java │ │ │ │ ├── NonNull.java │ │ │ │ ├── integration │ │ │ │ ├── common │ │ │ │ │ └── TestCriteria.kt │ │ │ │ ├── array │ │ │ │ │ └── ArrayTest.kt │ │ │ │ ├── nesting │ │ │ │ │ ├── NestedClassTest.kt │ │ │ │ │ └── GsonNestTest.kt │ │ │ │ ├── fields │ │ │ │ │ ├── FieldAnnotationsTest.kt │ │ │ │ │ └── UseGetterAnnotationTest.kt │ │ │ │ ├── properties │ │ │ │ │ ├── SerializeNullsTest.kt │ │ │ │ │ ├── DelimiterTest.kt │ │ │ │ │ └── SubstitutionTest.kt │ │ │ │ ├── misc │ │ │ │ │ ├── UsingConstructorTest.kt │ │ │ │ │ └── InheritanceTest.kt │ │ │ │ ├── enums │ │ │ │ │ └── EnumTest.kt │ │ │ │ └── extension │ │ │ │ │ ├── SizeExtensionTest.kt │ │ │ │ │ └── RemoveInvalidElementsTest.kt │ │ │ │ ├── TestUtils.kt │ │ │ │ └── unit │ │ │ │ ├── model │ │ │ │ └── FieldInfoTestFactory.kt │ │ │ │ └── adapter │ │ │ │ └── standard │ │ │ │ └── model │ │ │ │ └── MandatoryFieldInfoFactoryTest.kt │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ ├── gradle │ │ │ │ └── incremental.annotation.processors │ │ │ │ └── services │ │ │ │ └── javax.annotation.processing.Processor │ │ │ └── java │ │ │ └── gsonpath │ │ │ ├── adapter │ │ │ ├── standard │ │ │ │ ├── model │ │ │ │ │ ├── FieldPath.kt │ │ │ │ │ ├── GsonObjectMetadata.kt │ │ │ │ │ ├── GsonModels.kt │ │ │ │ │ ├── MandatoryFieldInfoFactory.kt │ │ │ │ │ ├── SerializedNameFetcher.kt │ │ │ │ │ ├── FieldPathFetcher.kt │ │ │ │ │ └── GsonObjectValidator.kt │ │ │ │ ├── adapter │ │ │ │ │ ├── write │ │ │ │ │ │ └── WriteParams.kt │ │ │ │ │ ├── properties │ │ │ │ │ │ ├── AutoGsonAdapterProperties.kt │ │ │ │ │ │ ├── PropertyFetcher.kt │ │ │ │ │ │ └── AdapterCommonPropertiesFactory.kt │ │ │ │ │ ├── read │ │ │ │ │ │ └── ReadParams.kt │ │ │ │ │ └── AdapterModelMetadata.kt │ │ │ │ ├── interf │ │ │ │ │ └── InterfaceModelMetadata.kt │ │ │ │ ├── extension │ │ │ │ │ ├── ExtensionsLoader.kt │ │ │ │ │ └── range │ │ │ │ │ │ └── RangeFunctions.kt │ │ │ │ ├── StandardAdapterFactory.kt │ │ │ │ └── factory │ │ │ │ │ └── TypeAdapterFactoryHandlersFactory.kt │ │ │ ├── common │ │ │ │ ├── GsonSubTypeResult.kt │ │ │ │ └── SubTypeMetadata.kt │ │ │ ├── util │ │ │ │ ├── NullableUtil.kt │ │ │ │ └── TypeSpecExt.kt │ │ │ ├── enums │ │ │ │ ├── EnumAdapterProperties.kt │ │ │ │ ├── EnumAdapterFactory.kt │ │ │ │ └── EnumFieldLabelMapper.kt │ │ │ ├── Constants.kt │ │ │ ├── AdapterFactory.kt │ │ │ └── AdapterMethodBuilder.kt │ │ │ ├── dependencies │ │ │ └── Dependencies.kt │ │ │ ├── util │ │ │ ├── Logger.kt │ │ │ └── FieldNamingPolicyMapper.kt │ │ │ └── LazyFactoryMetadata.kt │ ├── gradle.properties │ └── build.gradle └── base │ ├── gradle.properties │ ├── src │ └── main │ │ └── java │ │ └── gsonpath │ │ ├── ProcessingException.kt │ │ ├── util │ │ ├── FileWriter.kt │ │ ├── MethodSpecExt.kt │ │ ├── ElementExt.kt │ │ ├── TypeSpecExt.kt │ │ ├── SunTreesProvider.kt │ │ ├── DefaultValueDetector.kt │ │ └── FieldGetterFinder.kt │ │ ├── compiler │ │ ├── ExtensionFieldMetadata.kt │ │ └── SharedFunctions.kt │ │ └── model │ │ ├── FieldType.kt │ │ └── FieldInfo.kt │ └── build.gradle ├── scripts ├── jacoco-setup.gradle └── clean-util.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── settings.gradle ├── .gitignore ├── sample-base ├── build.gradle └── src │ └── main │ └── java │ └── gsonpath │ └── SampleAdapterFactory.java ├── gradle.properties ├── .travis.yml ├── LICENSE.txt └── guides └── path_substitution.md /.jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: 2 | - oraclejdk7 -------------------------------------------------------------------------------- /sample/src/test/resources/MandatoryTestJson.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /library/src/test/resources/sample.json: -------------------------------------------------------------------------------- 1 | [ 2 | "1", "a", "b", 4 3 | ] -------------------------------------------------------------------------------- /library-kt/src/test/resources/sample.json: -------------------------------------------------------------------------------- 1 | [ 2 | "1", "a", "b", 4 3 | ] -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /scripts/jacoco-setup.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'jacoco' 2 | 3 | jacoco { 4 | toolVersion = "0.8.2" 5 | } 6 | -------------------------------------------------------------------------------- /compiler/standard/src/main/resources/META-INF/gradle/incremental.annotation.processors: -------------------------------------------------------------------------------- 1 | gsonpath.GsonProcessor,dynamic -------------------------------------------------------------------------------- /compiler/standard/src/main/resources/META-INF/services/javax.annotation.processing.Processor: -------------------------------------------------------------------------------- 1 | gsonpath.GsonProcessor -------------------------------------------------------------------------------- /library/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=gsonpath 2 | POM_NAME=gsonpath 3 | VERSION_NAME=4.0.0 4 | POM_PACKAGING=jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LachlanMcKee/gsonpath/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /library-kt/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=gsonpath-kt 2 | POM_NAME=gsonpath-kt 3 | VERSION_NAME=4.0.0 4 | POM_PACKAGING=jar -------------------------------------------------------------------------------- /compiler/standard/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=gsonpath-compiler 2 | POM_NAME=gsonpath-compiler 3 | VERSION_NAME=4.0.0 4 | POM_PACKAGING=jar -------------------------------------------------------------------------------- /compiler/base/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=gsonpath-compiler-base 2 | POM_NAME=gsonpath-compiler-base 3 | VERSION_NAME=2.0.0 4 | POM_PACKAGING=jar -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/NonGsonPathFile.java: -------------------------------------------------------------------------------- 1 | package generator.factory; 2 | 3 | public class NonGsonPathFile { 4 | 5 | } -------------------------------------------------------------------------------- /sample/src/test/resources/DataClassJson_missing_values.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": { 3 | "child": { 4 | } 5 | }, 6 | "isBooleanTest1": false 7 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':library' 2 | include ':library-kt' 3 | include ':compiler:base' 4 | include ':compiler:standard' 5 | include ':sample' 6 | include ':sample-base' -------------------------------------------------------------------------------- /scripts/clean-util.gradle: -------------------------------------------------------------------------------- 1 | task cleanBuildDir(type: Delete) { 2 | delete "${projectDir}/build" 3 | delete "${projectDir}/out" 4 | } 5 | tasks.clean.dependsOn(cleanBuildDir) 6 | -------------------------------------------------------------------------------- /sample/src/test/resources/DataClassJson_all_values.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": { 3 | "child": { 4 | "value1": "test" 5 | } 6 | }, 7 | "isBooleanTest1": false 8 | } -------------------------------------------------------------------------------- /sample/src/test/resources/SealedClassSample_SingleType.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "type3", 3 | "common": { 4 | "name": "Type3 Example" 5 | }, 6 | "specific": { 7 | "stringTest": "123" 8 | } 9 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/TestLoaderSource.java: -------------------------------------------------------------------------------- 1 | package generator.factory; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | class TestLoaderSource { 7 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/source2/TestLoaderSource.java: -------------------------------------------------------------------------------- 1 | package generator.factory.source2; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | class TestLoaderSource { 7 | } -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/mandatory/MandatorySampleModel.java: -------------------------------------------------------------------------------- 1 | package gsonpath.mandatory; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | class MandatorySampleModel { 7 | int test; 8 | } 9 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/source2/TestLoaderSource2.java: -------------------------------------------------------------------------------- 1 | package generator.factory.source2; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | class TestLoaderSource2 { 7 | } -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/TestGsonTypeFactory.java: -------------------------------------------------------------------------------- 1 | package gsonpath; 2 | 3 | import com.google.gson.TypeAdapterFactory; 4 | 5 | @SampleAdapterFactory 6 | public interface TestGsonTypeFactory extends TypeAdapterFactory { 7 | } 8 | -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/adapter/subType/TypesList.java: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.subType; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | interface TypesList { 7 | Type[] getItems(); 8 | } 9 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/generics/classes/IntermediateTest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.generics.classes; 2 | 3 | class IntermediateTest extends BaseTest { 4 | V value3; 5 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/generics/interfaces/IntermediateTest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.generics.interfaces; 2 | 3 | interface IntermediateTest extends BaseTest { 4 | V getValue3(); 5 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/TestGsonTypeFactoryAsClass.java: -------------------------------------------------------------------------------- 1 | package generator.factory; 2 | 3 | import gsonpath.annotation.AutoGsonAdapterFactory; 4 | 5 | @AutoGsonAdapterFactory 6 | public class TestGsonTypeFactoryAsClass { 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Folders 2 | Build/ 3 | .gradle/ 4 | out/ 5 | 6 | # IntelliJ Files 7 | .idea/ 8 | *.iml 9 | 10 | # Android Folders/Files 11 | build.xml 12 | local.properties 13 | signing.properties 14 | *.keystore 15 | 16 | # Vim Temp files 17 | *~ 18 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/model/FieldPath.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.model 2 | 3 | sealed class FieldPath { 4 | data class Standard(val path: String) : FieldPath() 5 | data class Nested(val path: String) : FieldPath() 6 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/empty/annotation_only/TestAnnotationOnly.java: -------------------------------------------------------------------------------- 1 | package generator.standard.empty.annotation_only; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public class TestAnnotationOnly { 7 | } -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/Nullable.java: -------------------------------------------------------------------------------- 1 | package gsonpath; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.SOURCE) 6 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 7 | @Inherited 8 | public @interface Nullable { 9 | } 10 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/TestGsonTypeFactoryNoInterfaces.java: -------------------------------------------------------------------------------- 1 | package generator.factory; 2 | 3 | import gsonpath.annotation.AutoGsonAdapterFactory; 4 | 5 | @AutoGsonAdapterFactory 6 | public interface TestGsonTypeFactoryNoInterfaces { 7 | } 8 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/failures/TypesList_NoKeys.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.failures; 2 | 3 | import gsonpath.annotation.GsonSubtype; 4 | 5 | @GsonSubtype( 6 | jsonKeys = {} 7 | ) 8 | public class TypesList_NoKeys { 9 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/inheritance/TestInheritance.java: -------------------------------------------------------------------------------- 1 | package generator.standard.inheritance; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public class TestInheritance extends TestInheritanceBase { 7 | } -------------------------------------------------------------------------------- /sample-base/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply from: "${project.rootDir}/scripts/clean-util.gradle" 3 | 4 | targetCompatibility = JavaVersion.VERSION_1_8 5 | sourceCompatibility = JavaVersion.VERSION_1_8 6 | 7 | dependencies { 8 | compile project(":library") 9 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/Nullable.java: -------------------------------------------------------------------------------- 1 | package gsonpath; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 7 | @Inherited 8 | public @interface Nullable { 9 | } 10 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/custom_serialized_name_annotation/GsonNest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.custom_serialized_name_annotation; 2 | 3 | import gsonpath.annotation.NestedJson; 4 | 5 | @NestedJson("nest") 6 | public @interface GsonNest { 7 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/generics/classes/GenericsTest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.generics.classes; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | class GenericsTest extends IntermediateTest { 7 | } -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/NonNull.java: -------------------------------------------------------------------------------- 1 | package gsonpath; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.SOURCE) 6 | @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) 7 | @Inherited 8 | public @interface NonNull { 9 | } 10 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/common/GsonSubTypeResult.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.common 2 | 3 | import com.squareup.javapoet.MethodSpec 4 | 5 | data class GsonSubTypeResult( 6 | val readMethodSpecs: MethodSpec, 7 | val writeMethodSpecs: MethodSpec 8 | ) -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/util/NullableUtil.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.util 2 | 3 | object NullableUtil { 4 | fun isNullableKeyword(keyword: String): Boolean { 5 | return arrayOf("NonNull", "Nonnull", "NotNull", "Notnull").contains(keyword) 6 | } 7 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/generics/interfaces/GenericsTest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.generics.interfaces; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | interface GenericsTest extends IntermediateTest { 7 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Dec 30 13:58:45 AEDT 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-bin.zip 7 | -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/NonNull.java: -------------------------------------------------------------------------------- 1 | package gsonpath; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) 7 | @Inherited 8 | public @interface NonNull { 9 | } 10 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/interf/invalid/TestValidInterface_ReturningVoid.java: -------------------------------------------------------------------------------- 1 | package generator.interf.invalid; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public interface TestValidInterface_ReturningVoid { 7 | void getInvalid(); 8 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/generics/classes/BaseTest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.generics.classes; 2 | 3 | import java.util.Map; 4 | 5 | class BaseTest { 6 | GENERIC_1 value1; 7 | 8 | Map value2; 9 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/inheritance/TestInheritanceBase.java: -------------------------------------------------------------------------------- 1 | package generator.standard.inheritance; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class TestInheritanceBase { 6 | @SerializedName("Json1") 7 | public int value1; 8 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/field_types/generics/TestGenerics.java: -------------------------------------------------------------------------------- 1 | package generator.standard.field_types.generics; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public class TestGenerics { 7 | public java.util.List value1; 8 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/source3/TestLoaderSource.java: -------------------------------------------------------------------------------- 1 | package generator.factory.source3; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | class TestLoaderSource { 7 | @AutoGsonAdapter 8 | static class Inner { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/failures/TypesList_NoGsonSubtypeGetter.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.failures; 2 | 3 | import gsonpath.annotation.GsonSubtype; 4 | 5 | @GsonSubtype( 6 | jsonKeys = {"type"} 7 | ) 8 | public class TypesList_NoGsonSubtypeGetter { 9 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/indirectly_annotated/IndirectSubType.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.indirectly_annotated; 2 | 3 | import gsonpath.annotation.GsonSubtype; 4 | 5 | @GsonSubtype( 6 | jsonKeys = {"type"} 7 | ) 8 | public @interface IndirectSubType { 9 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/field_types/custom_field/TestCustomField.java: -------------------------------------------------------------------------------- 1 | package generator.standard.field_types.custom_field; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public class TestCustomField { 7 | public java.util.Currency value1; 8 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/TestGsonTypeFactoryIncorrectInterfaces.java: -------------------------------------------------------------------------------- 1 | package generator.factory; 2 | 3 | import gsonpath.annotation.AutoGsonAdapterFactory; 4 | 5 | @AutoGsonAdapterFactory 6 | public interface TestGsonTypeFactoryIncorrectInterfaces extends java.io.Serializable { 7 | } 8 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/interf/invalid/TestValidInterface_WithParameters.java: -------------------------------------------------------------------------------- 1 | package generator.interf.invalid; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public interface TestValidInterface_WithParameters { 7 | int getInvalid(int invalidParameter); 8 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/generics/interfaces/BaseTest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.generics.interfaces; 2 | 3 | import java.util.Map; 4 | 5 | interface BaseTest { 6 | GENERIC_1 getValue1(); 7 | 8 | Map getValue2(); 9 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/TestGsonTypeFactory.java: -------------------------------------------------------------------------------- 1 | package generator.factory; 2 | 3 | import com.google.gson.TypeAdapterFactory; 4 | import gsonpath.annotation.AutoGsonAdapterFactory; 5 | 6 | @AutoGsonAdapterFactory 7 | public interface TestGsonTypeFactory extends TypeAdapterFactory { 8 | } 9 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/TestGsonTypeFactory2.java: -------------------------------------------------------------------------------- 1 | package generator.factory; 2 | 3 | import com.google.gson.TypeAdapterFactory; 4 | import gsonpath.annotation.AutoGsonAdapterFactory; 5 | 6 | @AutoGsonAdapterFactory 7 | public interface TestGsonTypeFactory2 extends TypeAdapterFactory { 8 | } 9 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/TestGsonTypeFactory.java: -------------------------------------------------------------------------------- 1 | package generator.standard; 2 | 3 | import com.google.gson.TypeAdapterFactory; 4 | import gsonpath.annotation.AutoGsonAdapterFactory; 5 | 6 | @AutoGsonAdapterFactory 7 | public interface TestGsonTypeFactory extends TypeAdapterFactory { 8 | } 9 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/nested_json/root_nesting/TestRootNesting.java: -------------------------------------------------------------------------------- 1 | package generator.standard.nested_json.root_nesting; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter(rootField = "Root.Nest1") 6 | public class TestRootNesting { 7 | public int value1; 8 | } -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/ProcessingException.kt: -------------------------------------------------------------------------------- 1 | package gsonpath 2 | 3 | import javax.lang.model.element.Element 4 | 5 | /** 6 | * Represents that something has gone wrong during annotation processing. 7 | */ 8 | class ProcessingException(override val message: String, val element: Element? = null) : Exception(message) 9 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/generics/interfaces_and_classs/BaseTest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.generics.interfaces_and_classs; 2 | 3 | import java.util.Map; 4 | 5 | interface BaseTest { 6 | GENERIC_1 getValue1(); 7 | 8 | Map getValue2(); 9 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/nested_class/TestNestedClass.java: -------------------------------------------------------------------------------- 1 | package generator.standard.nested_class; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | public class TestNestedClass { 6 | @AutoGsonAdapter 7 | public static class Nested { 8 | public int value1; 9 | } 10 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/empty/invalid_fields/TestInvalidFields.java: -------------------------------------------------------------------------------- 1 | package generator.standard.empty.invalid_fields; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter(ignoreNonAnnotatedFields = true) 6 | public class TestInvalidFields { 7 | public java.lang.String element1; 8 | } -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/util/FileWriter.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.util 2 | 3 | import javax.annotation.processing.Filer 4 | import javax.annotation.processing.ProcessingEnvironment 5 | 6 | class FileWriter(private val processingEnvironment: ProcessingEnvironment) { 7 | val filer: Filer 8 | get() = processingEnvironment.filer 9 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/exception/JsonFieldMissingException.java: -------------------------------------------------------------------------------- 1 | package gsonpath.exception; 2 | 3 | import com.google.gson.JsonParseException; 4 | 5 | public abstract class JsonFieldMissingException extends JsonParseException { 6 | public JsonFieldMissingException(String message) { 7 | super(message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/kotlin/CustomAnnotation.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.kotlin 2 | 3 | import gsonpath.GsonFieldValidationType 4 | import gsonpath.annotation.AutoGsonAdapter 5 | 6 | @Retention(AnnotationRetention.RUNTIME) 7 | @AutoGsonAdapter(fieldValidationType = [GsonFieldValidationType.VALIDATE_EXPLICIT_NON_NULL]) 8 | annotation class CustomAnnotation -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/adapter/standard/extension/flatten/FlattenModel.java: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.extension.flatten; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | import gsonpath.extension.annotation.FlattenJson; 5 | 6 | @AutoGsonAdapter 7 | interface FlattenModel { 8 | @FlattenJson 9 | String getValue(); 10 | } 11 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/extension/size/valid/mutable/TestMutableSize.java: -------------------------------------------------------------------------------- 1 | package generator.standard.size.valid.nullable; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | import gsonpath.extension.annotation.Size; 5 | 6 | @AutoGsonAdapter 7 | public class TestMutableSize { 8 | @Size(value = 1) 9 | String[] value1; 10 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/exception/JsonFieldNullException.java: -------------------------------------------------------------------------------- 1 | package gsonpath.exception; 2 | 3 | public class JsonFieldNullException extends JsonFieldMissingException { 4 | public JsonFieldNullException(String field, String className) { 5 | super("Mandatory JSON element '" + field + "' was null for class '" + className + "'"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/kotlin/DataClassSample.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.kotlin 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | @CustomAnnotation 6 | data class DataClassSample( 7 | @SerializedName("parent.child.") 8 | val value1: String, 9 | val isBooleanTest1: Boolean, 10 | val isBooleanTest2: Boolean? 11 | ) -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/failures/TypesList_BlankFieldName.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.failures; 2 | 3 | import gsonpath.annotation.GsonSubtype; 4 | 5 | @GsonSubtype( 6 | jsonKeys = {""} 7 | ) 8 | public class TypesList_BlankFieldName { 9 | public class Type1 extends TypesList_BlankFieldName { 10 | } 11 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/exception/JsonFieldNoKeyException.java: -------------------------------------------------------------------------------- 1 | package gsonpath.exception; 2 | 3 | public class JsonFieldNoKeyException extends JsonFieldMissingException { 4 | public JsonFieldNoKeyException(String field, String className) { 5 | super("Mandatory JSON element '" + field + "' was not found within class '" + className + "'"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/common/TestCriteria.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.common 2 | 3 | class TestCriteria(val resourcePath: String, 4 | val relativeSourceNames: List = emptyList(), 5 | val relativeGeneratedNames: List = emptyList(), 6 | val absoluteSourceNames: List = emptyList()) -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/interf/inheritance/TestUsingInheritanceBase.java: -------------------------------------------------------------------------------- 1 | package generator.interf.inheritance; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public interface TestUsingInheritanceBase { 6 | @SerializedName("Json1.Nest1") 7 | Integer getValue1(); 8 | 9 | Integer getValue2(); 10 | 11 | Integer getValue3(); 12 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/field_annotations/exclude/TestExclude.java: -------------------------------------------------------------------------------- 1 | package generator.standard.field_annotations.exclude; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | import gsonpath.annotation.ExcludeField; 5 | 6 | @AutoGsonAdapter 7 | public class TestExclude { 8 | public int element1; 9 | @ExcludeField 10 | public int element2; 11 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/substitution/valid/TestSubstitutionBase.java: -------------------------------------------------------------------------------- 1 | package generator.standard.substitution.valid; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class TestSubstitutionBase { 6 | @SerializedName("{SUB_1}.Json1") 7 | public int value1; 8 | @SerializedName("{SUB_2}.Json1") 9 | public int value2; 10 | } -------------------------------------------------------------------------------- /library-kt/src/main/java/gsonpath/GsonResult.kt: -------------------------------------------------------------------------------- 1 | package gsonpath 2 | 3 | import com.google.gson.JsonParseException 4 | 5 | /** 6 | * Used to keep track of succesful and unsucessful deserializations. 7 | */ 8 | sealed class GsonResult { 9 | data class Success(val value: T) : GsonResult() 10 | data class Failure(val exception: JsonParseException) : GsonResult() 11 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/delimiter/standard/TestStandardDelimiter.java: -------------------------------------------------------------------------------- 1 | package generator.standard.delimiter.standard; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | public class TestStandardDelimiter { 8 | @SerializedName("Json1.Nest1") 9 | public int value1; 10 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/naming_policy/identity/TestNamePolicyIdentity.java: -------------------------------------------------------------------------------- 1 | package generator.standard.naming_policy.identity; 2 | 3 | import com.google.gson.FieldNamingPolicy; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter(fieldNamingPolicy = FieldNamingPolicy.IDENTITY) 7 | public class TestNamePolicyIdentity { 8 | public int testValue; 9 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/adapter/write/WriteParams.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.adapter.write 2 | 3 | import com.squareup.javapoet.ClassName 4 | import gsonpath.adapter.standard.model.GsonObject 5 | 6 | data class WriteParams( 7 | val elementClassName: ClassName, 8 | val rootElements: GsonObject, 9 | val serializeNulls: Boolean 10 | ) -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/nested_json/field_nesting_autocomplete_inheritance/TestFieldNestingAutocompleteBase.java: -------------------------------------------------------------------------------- 1 | package generator.standard.nested_json.field_nesting_autocomplete_inheritance; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public interface TestFieldNestingAutocompleteBase { 6 | @SerializedName("Json1.") 7 | public int getValue1(); 8 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/processor_errors/TestInvalidFlattenJsonError.java: -------------------------------------------------------------------------------- 1 | package generator.standard.processor_errors; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | public class TestInvalidFlattenJsonError { 8 | @SerializedName("element1") 9 | public Integer element1; 10 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/annotation/GsonSubtypeGetter.java: -------------------------------------------------------------------------------- 1 | package gsonpath.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface GsonSubtypeGetter { 11 | } 12 | -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/compiler/ExtensionFieldMetadata.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.compiler 2 | 3 | import gsonpath.model.FieldInfo 4 | 5 | /** 6 | * Metadata about the field being read by the parent processor 7 | */ 8 | data class ExtensionFieldMetadata( 9 | val fieldInfo: FieldInfo, 10 | val variableName: String, 11 | val jsonPath: String, 12 | val isRequired: Boolean) -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/custom_adapter_annotation/TestCustomAutoGsonAdapterModel.java: -------------------------------------------------------------------------------- 1 | package generator.standard.custom_adapter_annotation; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | @CustomAutoGsonAdapter 6 | public class TestCustomAutoGsonAdapterModel { 7 | @SerializedName("path$") 8 | Integer expectedValue; 9 | 10 | String ignored; 11 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/delimiter/custom/TestCustomDelimiter.java: -------------------------------------------------------------------------------- 1 | package generator.standard.delimiter.custom; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter(flattenDelimiter = '$') 7 | public class TestCustomDelimiter { 8 | @SerializedName("Json1$Nest1") 9 | public int value1; 10 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/processor_errors/TestInvalidFieldTypeError.java: -------------------------------------------------------------------------------- 1 | package generator.standard.processor_errors; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | public class TestInvalidFieldTypeError { 8 | @SerializedName("element1") 9 | public java.lang.Object element1; 10 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/GsonSafeList.java: -------------------------------------------------------------------------------- 1 | package gsonpath; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * A list that stores only valid results when parsing via Gson. 7 | *

8 | * Any elements being deserialied that throw an exception are removed from the list. 9 | * 10 | * @param the element type within the list 11 | */ 12 | public final class GsonSafeList extends ArrayList { 13 | } 14 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/naming_policy/upper_camel_case/TestNamePolicyUpperCamelCase.java: -------------------------------------------------------------------------------- 1 | package generator.standard.naming_policy.upper_camel_case; 2 | 3 | import com.google.gson.FieldNamingPolicy; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter(fieldNamingPolicy = FieldNamingPolicy.UPPER_CAMEL_CASE) 7 | public class TestNamePolicyUpperCamelCase { 8 | public int testValue; 9 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/generics/interfaces_and_classs/GenericsTest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.generics.interfaces_and_classs; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | class GenericsTest extends IntermediateTest { 7 | Double value3; 8 | 9 | @Override 10 | public Double getValue3() { 11 | return value3; 12 | } 13 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/exception/JsonUnexpectedEnumValueException.java: -------------------------------------------------------------------------------- 1 | package gsonpath.exception; 2 | 3 | import com.google.gson.JsonParseException; 4 | 5 | public class JsonUnexpectedEnumValueException extends JsonParseException { 6 | public JsonUnexpectedEnumValueException(String value, String className) { 7 | super("Unexpected enum value '" + value + "' for class '" + className + "'"); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/interf/java8/TestJava8Interface.java: -------------------------------------------------------------------------------- 1 | package generator.interf.java8; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public interface TestJava8Interface { 7 | Integer getValue1(); 8 | 9 | default Void testDefaultIgnored() { 10 | return null; 11 | } 12 | 13 | static Void testStaticIgnored() { 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/naming_policy/lowercase_dashes/TestNamePolicyLowerCaseDashes.java: -------------------------------------------------------------------------------- 1 | package generator.standard.naming_policy.lowercase_dashes; 2 | 3 | import com.google.gson.FieldNamingPolicy; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter(fieldNamingPolicy = FieldNamingPolicy.LOWER_CASE_WITH_DASHES) 7 | public class TestNamePolicyLowerCaseDashes { 8 | public int testValue; 9 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/nested_json/field_nesting_autocomplete/TestFieldNestingAutocomplete.java: -------------------------------------------------------------------------------- 1 | package generator.standard.nested_json.field_nesting_autocomplete; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | public class TestFieldNestingAutocomplete { 8 | @SerializedName("Json1.") 9 | public int value1; 10 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/processor_errors/TestSerializedNameAlternateUsedError.java: -------------------------------------------------------------------------------- 1 | package generator.standard.processor_errors; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | public class TestSerializedNameAlternateUsedError { 8 | @SerializedName(value = "foo", alternate = "bar") 9 | public int element1; 10 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/failures/TypesList_DuplicateKeys.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.failures; 2 | 3 | import gsonpath.annotation.GsonSubtype; 4 | 5 | @GsonSubtype( 6 | jsonKeys = {"type1", "type1"} 7 | ) 8 | public class TypesList_DuplicateKeys { 9 | public class Type1 extends TypesList_DuplicateKeys { 10 | } 11 | 12 | public class Type2 extends TypesList_DuplicateKeys { 13 | } 14 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/processor_errors/TestDuplicateFieldError.java: -------------------------------------------------------------------------------- 1 | package generator.standard.processor_errors; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | public class TestDuplicateFieldError { 8 | @SerializedName("value") 9 | public double value1; 10 | 11 | @SerializedName("value") 12 | public double value2; 13 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/enums/EnumAdapterProperties.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.enums 2 | 3 | import com.squareup.javapoet.ClassName 4 | 5 | data class EnumAdapterProperties( 6 | val enumTypeName: ClassName, 7 | val fields: List, 8 | val defaultValue: EnumField? 9 | ) { 10 | data class EnumField( 11 | val enumValueTypeName: ClassName, 12 | val label: String 13 | ) 14 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/naming_policy/lowercase_underscores/TestNamePolicyLowerCaseUnderscores.java: -------------------------------------------------------------------------------- 1 | package generator.standard.naming_policy.lowercase_underscores; 2 | 3 | import com.google.gson.FieldNamingPolicy; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter(fieldNamingPolicy = FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) 7 | public class TestNamePolicyLowerCaseUnderscores { 8 | public int testValue; 9 | } -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/vanilla/PeopleModelVanilla.java: -------------------------------------------------------------------------------- 1 | package gsonpath.vanilla; 2 | 3 | public class PeopleModelVanilla { 4 | public People[] people; 5 | 6 | public static class People { 7 | public Person person; 8 | } 9 | 10 | public static class Person { 11 | public Names names; 12 | } 13 | 14 | public static class Names { 15 | public String first; 16 | public String last; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/naming_policy/upper_camel_case_spaces/TestNamePolicyUpperCamelCaseSpaces.java: -------------------------------------------------------------------------------- 1 | package generator.standard.naming_policy.upper_camel_case_spaces; 2 | 3 | import com.google.gson.FieldNamingPolicy; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter(fieldNamingPolicy = FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES) 7 | public class TestNamePolicyUpperCamelCaseSpaces { 8 | public int testValue; 9 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/annotation/ExcludeField.java: -------------------------------------------------------------------------------- 1 | package gsonpath.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Specifies that the annotated field will not be added to the auto generated 7 | * {@link com.google.gson.TypeAdapter} when using the {@link AutoGsonAdapter} 8 | * annotation. 9 | */ 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Target(ElementType.FIELD) 12 | @Inherited 13 | public @interface ExcludeField { 14 | } 15 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/empty/ignored_fields/TestIgnoredFields.java: -------------------------------------------------------------------------------- 1 | package generator.standard.empty.ignored_fields; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public class TestIgnoredFields { 7 | private static final String TAG = TestIgnoredFields.class.getSimpleName(); 8 | public static final int element1 = 1; 9 | public final int element2 = 2; 10 | public static int element3 = 3; 11 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/one_argument/TypeGsonSubType.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.one_argument; 2 | 3 | import gsonpath.annotation.GsonSubtype; 4 | import gsonpath.annotation.GsonSubtypeGetter; 5 | 6 | @GsonSubtype( 7 | jsonKeys = {"type"} 8 | ) 9 | public class TypeGsonSubType { 10 | @GsonSubtypeGetter 11 | static Class getSubType1(String type) { 12 | return null; 13 | } 14 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/failures/TypesList_IncorrectReturnType.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.failures; 2 | 3 | import gsonpath.annotation.GsonSubtype; 4 | import gsonpath.annotation.GsonSubtypeGetter; 5 | 6 | @GsonSubtype( 7 | jsonKeys = {"type"} 8 | ) 9 | public class TypesList_IncorrectReturnType { 10 | 11 | @GsonSubtypeGetter 12 | static Class getSubType() { 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /library-kt/src/main/java/gsonpath/GsonResultList.kt: -------------------------------------------------------------------------------- 1 | package gsonpath 2 | 3 | /** 4 | * A list that stores valid and invalid results when parsing via Gson. 5 | * 6 | * All succesfully parsed results are wrapped with GsonResult.Success, and all results that 7 | * threw an exception are wrapped with Failure.Failure 8 | * 9 | * @param the element type within the list 10 | */ 11 | class GsonResultList(private val list: List>) : List> by list 12 | -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/annotation/GsonPathGenerated.java: -------------------------------------------------------------------------------- 1 | package gsonpath.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Denotes that the class was generated by the gson-path library. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.TYPE) 13 | public @interface GsonPathGenerated { 14 | } 15 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/delimiter/multiple/TestMultipleDelimiters.java: -------------------------------------------------------------------------------- 1 | package generator.standard.delimiter.multiple; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter(flattenDelimiter = '$') 7 | public class TestMultipleDelimiters { 8 | @SerializedName("Json1$Nest1") 9 | public int value1; 10 | 11 | @SerializedName("Json2.Nest1") 12 | public int value2; 13 | } -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/generated/PersonModelGenerated.java: -------------------------------------------------------------------------------- 1 | package gsonpath.generated; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | public interface PersonModelGenerated { 8 | PersonModel[] getPeople(); 9 | 10 | @AutoGsonAdapter(rootField = "person.names") 11 | interface PersonModel { 12 | @SerializedName("first") 13 | String getFirstName(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/common/SubTypeMetadata.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.common 2 | 3 | import com.squareup.javapoet.TypeName 4 | 5 | data class SubTypeMetadata( 6 | val gsonSubTypeFieldInfo: List, 7 | val classGetterMethodName: String) 8 | 9 | data class GsonSubTypeFieldInfo( 10 | val jsonKey: String, 11 | val variableName: String, 12 | val parameterTypeName: TypeName, 13 | val nullable: Boolean) 14 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/interf/InterfaceModelMetadata.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.interf 2 | 3 | import com.squareup.javapoet.TypeName 4 | import javax.lang.model.element.Element 5 | import javax.lang.model.type.TypeMirror 6 | 7 | data class InterfaceModelMetadata( 8 | val typeName: TypeName, 9 | val fieldName: String, 10 | val enclosedElement: Element, 11 | val methodName: String, 12 | val returnTypeMirror: TypeMirror) -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/extension/invalid/mutable/TestMutableRemoveInvalidElements.java: -------------------------------------------------------------------------------- 1 | package generator.standard.invalid.mutable; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | import gsonpath.extension.annotation.RemoveInvalidElements; 5 | 6 | import java.util.List; 7 | 8 | @AutoGsonAdapter 9 | public class TestMutableRemoveInvalidElements { 10 | @RemoveInvalidElements 11 | String[] value1; 12 | 13 | @RemoveInvalidElements 14 | List value2; 15 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/serialize_nulls/TestSerializeNulls.java: -------------------------------------------------------------------------------- 1 | package generator.standard.class_annotations.serialize_nulls; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter(serializeNulls = true) 6 | public class TestSerializeNulls { 7 | public int value1; 8 | public double value2; 9 | public boolean value3; 10 | public String value4; 11 | public Integer value5; 12 | public Double value6; 13 | public Boolean value7; 14 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/field_types/primitives/valid/TestValidPrimitives.java: -------------------------------------------------------------------------------- 1 | package generator.standard.field_types.primitives.valid; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public class TestValidPrimitives { 7 | public boolean value1; 8 | public int value2; 9 | public double value3; 10 | public long value4; 11 | public byte value5; 12 | public short value6; 13 | public float value7; 14 | public char value8; 15 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/substitution/valid/TestSubstitutionImpl1.java: -------------------------------------------------------------------------------- 1 | package generator.standard.substitution.valid; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | import gsonpath.annotation.PathSubstitution; 5 | 6 | @AutoGsonAdapter(substitutions = { 7 | @PathSubstitution(original = "SUB_1", replacement = "Impl1_A"), 8 | @PathSubstitution(original = "SUB_2", replacement = "Impl1_B") 9 | }) 10 | public class TestSubstitutionImpl1 extends TestSubstitutionBase { 11 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/substitution/valid/TestSubstitutionImpl2.java: -------------------------------------------------------------------------------- 1 | package generator.standard.substitution.valid; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | import gsonpath.annotation.PathSubstitution; 5 | 6 | @AutoGsonAdapter(substitutions = { 7 | @PathSubstitution(original = "SUB_1", replacement = "Impl2_A"), 8 | @PathSubstitution(original = "SUB_2", replacement = "Impl2_B") 9 | }) 10 | public class TestSubstitutionImpl2 extends TestSubstitutionBase { 11 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/model/GsonObjectMetadata.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.model 2 | 3 | import com.google.gson.FieldNamingPolicy 4 | import gsonpath.GsonFieldValidationType 5 | import gsonpath.annotation.PathSubstitution 6 | 7 | data class GsonObjectMetadata( 8 | val flattenDelimiter: Char, 9 | val gsonFieldNamingPolicy: FieldNamingPolicy, 10 | val gsonFieldValidationType: GsonFieldValidationType, 11 | val pathSubstitutions: List) -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/field_policy/default_value/TestValidateWithDefaultValue.java: -------------------------------------------------------------------------------- 1 | package generator.standard.field_policy.validate_explicit_non_null; 2 | 3 | import gsonpath.GsonFieldValidationType; 4 | import gsonpath.NonNull; 5 | import gsonpath.annotation.AutoGsonAdapter; 6 | 7 | @AutoGsonAdapter(fieldValidationType = GsonFieldValidationType.VALIDATE_EXPLICIT_NON_NULL) 8 | public class TestValidateWithDefaultValue { 9 | @NonNull 10 | public Integer mandatoryWithDefault = 0; 11 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/substitution/errors/TestSubstitutionError_DuplicateKeys.java: -------------------------------------------------------------------------------- 1 | package generator.standard.substitution.valid; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | import gsonpath.annotation.PathSubstitution; 5 | 6 | @AutoGsonAdapter(substitutions = { 7 | @PathSubstitution(original = "KEY_1", replacement = "REPLACE_1"), 8 | @PathSubstitution(original = "KEY_1", replacement = "REPLACE_2") 9 | }) 10 | public class TestSubstitutionError_DuplicateKeys { 11 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/interf/primitive/TestUsingPrimitives.java: -------------------------------------------------------------------------------- 1 | package generator.interf.primitive; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public interface TestUsingPrimitives { 7 | int getIntExample(); 8 | long getLongExample(); 9 | double getDoubleExample(); 10 | boolean getBooleanExample(); 11 | int[] getIntArrayExample(); 12 | long[] getLongArrayExample(); 13 | double[] getDoubleArrayExample(); 14 | boolean[] getBooleanArrayExample(); 15 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/interf/valid/TestValidInterface.java: -------------------------------------------------------------------------------- 1 | package generator.interf.valid; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | public interface TestValidInterface { 8 | @SerializedName("Json1.Nest1") 9 | Integer getValue1(); 10 | 11 | Integer getValue2(); 12 | 13 | @SerializedName("Json1.Nest3") 14 | Integer getValue3(); 15 | 16 | Integer getResult(); 17 | 18 | Integer getThat(); 19 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/Constants.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter 2 | 3 | import com.squareup.javapoet.AnnotationSpec 4 | import gsonpath.annotation.GsonPathGenerated 5 | 6 | object Constants { 7 | const val GSON = "gson" 8 | const val NULL = "null" 9 | const val IN = "in" 10 | const val OUT = "out" 11 | const val VALUE = "value" 12 | const val GET_ADAPTER = "$GSON.getAdapter" 13 | 14 | val GENERATED_ANNOTATION: AnnotationSpec = AnnotationSpec.builder(GsonPathGenerated::class.java).build() 15 | } -------------------------------------------------------------------------------- /sample/src/test/resources/InterfaceEqualityVariant1TestJson.json: -------------------------------------------------------------------------------- 1 | { 2 | "intExample": 1, 3 | "longExample": 1000, 4 | "doubleExample": 2.5, 5 | "booleanExample": true, 6 | "intArrayExample": [ 7 | 1, 8 | 2, 9 | 3 10 | ], 11 | "longArrayExample": [ 12 | 1000, 13 | 2000, 14 | 3000 15 | ], 16 | "doubleArrayExample": [ 17 | 2.5, 18 | 3.5, 19 | 4.5 20 | ], 21 | "booleanArrayExample": [ 22 | true, 23 | false 24 | ] 25 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/enums/with_default/TestEnumWithDefault.java: -------------------------------------------------------------------------------- 1 | package generator.enums.with_default; 2 | 3 | import com.google.gson.FieldNamingPolicy; 4 | import com.google.gson.annotations.SerializedName; 5 | import gsonpath.annotation.EnumGsonAdapter; 6 | 7 | @EnumGsonAdapter(fieldNamingPolicy = FieldNamingPolicy.LOWER_CASE_WITH_DASHES) 8 | enum TestEnumWithDefault { 9 | @EnumGsonAdapter.DefaultValue 10 | VALUE_ABC, 11 | VALUE_DEF, 12 | @SerializedName("custom") 13 | VALUE_GHI, 14 | VALUE_1 15 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/enums/without_default/TestEnumWithoutDefault.java: -------------------------------------------------------------------------------- 1 | package generator.enums.without_default; 2 | 3 | import com.google.gson.FieldNamingPolicy; 4 | import com.google.gson.annotations.SerializedName; 5 | import gsonpath.annotation.EnumGsonAdapter; 6 | 7 | @EnumGsonAdapter(fieldNamingPolicy = FieldNamingPolicy.LOWER_CASE_WITH_DASHES, ignoreDefaultValue = true) 8 | enum TestEnumWithoutDefault { 9 | VALUE_ABC, 10 | VALUE_DEF, 11 | @SerializedName("custom") 12 | VALUE_GHI, 13 | VALUE_1 14 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/field_types/boxed_primitives/TestBoxedPrimitives.java: -------------------------------------------------------------------------------- 1 | package generator.standard.field_types.boxed_primitives; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public class TestBoxedPrimitives { 7 | public String value1; 8 | public Boolean value2; 9 | public Integer value3; 10 | public Double value4; 11 | public Long value5; 12 | public Byte value6; 13 | public Short value7; 14 | public Float value8; 15 | public Character value9; 16 | } -------------------------------------------------------------------------------- /sample/src/test/resources/InterfaceEqualityVariant2TestJson.json: -------------------------------------------------------------------------------- 1 | { 2 | "intExample": -1, 3 | "longExample": -1000, 4 | "doubleExample": -2.5, 5 | "booleanExample": false, 6 | "intArrayExample": [ 7 | -1, 8 | -2, 9 | -3 10 | ], 11 | "longArrayExample": [ 12 | -1000, 13 | -2000, 14 | -3000 15 | ], 16 | "doubleArrayExample": [ 17 | -2.5, 18 | -3.5, 19 | -4.5 20 | ], 21 | "booleanArrayExample": [ 22 | false, 23 | true 24 | ] 25 | } -------------------------------------------------------------------------------- /sample-base/src/main/java/gsonpath/SampleAdapterFactory.java: -------------------------------------------------------------------------------- 1 | package gsonpath; 2 | 3 | import gsonpath.annotation.AutoGsonAdapterFactory; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | @AutoGsonAdapterFactory( 11 | fieldValidationType = GsonFieldValidationType.VALIDATE_EXPLICIT_NON_NULL 12 | ) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target(ElementType.TYPE) 15 | public @interface SampleAdapterFactory { 16 | } 17 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/extension/size/valid/immutable/TestImmutableSize.java: -------------------------------------------------------------------------------- 1 | package generator.standard.size.valid.nullable; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | import gsonpath.extension.annotation.Size; 5 | 6 | @AutoGsonAdapter 7 | public class TestImmutableSize { 8 | @Size(min = 0, max = 6, multiple = 2) 9 | private String[] value1; 10 | 11 | public TestImmutableSize(String[] value1) { 12 | this.value1 = value1; 13 | } 14 | 15 | public String[] getValue1() { 16 | return value1; 17 | } 18 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/two_arguments/TypeGsonSubType.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.two_arguments; 2 | 3 | import gsonpath.NonNull; 4 | import gsonpath.annotation.GsonSubtype; 5 | import gsonpath.annotation.GsonSubtypeGetter; 6 | 7 | import java.util.List; 8 | 9 | @GsonSubtype( 10 | jsonKeys = {"type1", "type2"} 11 | ) 12 | public class TypeGsonSubType { 13 | @GsonSubtypeGetter 14 | static Class getSubType1(@NonNull String type1, List type2) { 15 | return null; 16 | } 17 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/extension/annotation/RemoveInvalidElements.java: -------------------------------------------------------------------------------- 1 | package gsonpath.extension.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Inherited; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.Target; 7 | 8 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 9 | 10 | /** 11 | * Removes invalid elements from arrays/lists. 12 | */ 13 | @Retention(RUNTIME) 14 | @Target({ElementType.FIELD, ElementType.METHOD}) 15 | @Inherited 16 | public @interface RemoveInvalidElements { 17 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/generics/interfaces_and_classs/IntermediateTest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.generics.interfaces_and_classs; 2 | 3 | import java.util.Map; 4 | 5 | abstract class IntermediateTest implements BaseTest { 6 | T value1; 7 | Map value2; 8 | 9 | @Override 10 | public T getValue1() { 11 | return value1; 12 | } 13 | 14 | @Override 15 | public Map getValue2() { 16 | return value2; 17 | } 18 | 19 | public abstract V getValue3(); 20 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/extension/annotation/EmptyToNull.java: -------------------------------------------------------------------------------- 1 | package gsonpath.extension.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Inherited; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.Target; 7 | 8 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 9 | 10 | /** 11 | * Changes an empty object (of types map, list, array or string) to a null value. 12 | */ 13 | @Retention(RUNTIME) 14 | @Target({ElementType.FIELD, ElementType.METHOD}) 15 | @Inherited 16 | public @interface EmptyToNull { 17 | } -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/adapter/subType/TypesPojo.java: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.subType; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | interface TypesPojo { 8 | @SerializedName("items[0]") 9 | Type getItem0(); 10 | 11 | @SerializedName("items[1]") 12 | Type getItem1(); 13 | 14 | @SerializedName("items[2]") 15 | Type getItem2(); 16 | 17 | @SerializedName("items[3]") 18 | Type getItem3(); 19 | 20 | @SerializedName("items[4]") 21 | Type getItem4(); 22 | } 23 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/field_policy/validate_all_except_nullable/TestValidateAllExceptNullable.java: -------------------------------------------------------------------------------- 1 | package generator.standard.field_policy.validate_all_except_nullable; 2 | 3 | import gsonpath.GsonFieldValidationType; 4 | import gsonpath.Nullable; 5 | import gsonpath.annotation.AutoGsonAdapter; 6 | 7 | @AutoGsonAdapter(fieldValidationType = GsonFieldValidationType.VALIDATE_ALL_EXCEPT_NULLABLE) 8 | public class TestValidateAllExceptNullable { 9 | public Integer mandatory1; 10 | public Integer mandatory2; 11 | 12 | @Nullable 13 | public Integer optional1; 14 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/failures/TypesList_KeysAndParameterMismatch.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.failures; 2 | 3 | import gsonpath.annotation.GsonSubtype; 4 | import gsonpath.annotation.GsonSubtypeGetter; 5 | 6 | @GsonSubtype( 7 | jsonKeys = {"type"} 8 | ) 9 | public class TypesList_KeysAndParameterMismatch { 10 | 11 | @GsonSubtypeGetter 12 | static Class getSubType() { 13 | return Type1.class; 14 | } 15 | 16 | public class Type1 extends TypesList_KeysAndParameterMismatch { 17 | } 18 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/nested_json/field_nesting_autocomplete_inheritance/TestFieldNestingAutocomplete.java: -------------------------------------------------------------------------------- 1 | package generator.standard.nested_json.field_nesting_autocomplete_inheritance; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | public class TestFieldNestingAutocomplete implements TestFieldNestingAutocompleteBase { 7 | private int value1; 8 | 9 | public TestFieldNestingAutocomplete(int value1) { 10 | this.value1 = value1; 11 | } 12 | 13 | @Override 14 | public int getValue1() { 15 | return value1; 16 | } 17 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/nested_json/field_nesting/TestFieldNesting.java: -------------------------------------------------------------------------------- 1 | package generator.standard.nested_json.field_nesting; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | public class TestFieldNesting { 8 | @SerializedName("Json1") 9 | public int value1; 10 | 11 | @SerializedName("Json2.Nest1") 12 | public int value2; 13 | 14 | @SerializedName("Json2.Nest2.EndPoint1") 15 | public int value3; 16 | 17 | @SerializedName("Json2.Nest2.EndPoint2") 18 | public int value4; 19 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/processor_errors/TestInvalidFieldPathError.java: -------------------------------------------------------------------------------- 1 | package generator.standard.processor_errors; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | public class TestInvalidFieldPathError { 8 | public double value; 9 | 10 | /** 11 | * The error happens within this annotation since we assume that 'value' is a json object, 12 | * and yet we assume that 'value' is a double in the previous field. 13 | */ 14 | @SerializedName("value.record") 15 | public double record; 16 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | GROUP=net.lachlanmckee 2 | 3 | POM_DESCRIPTION=An annotation processor which generates Type Adapters for the Google Gson library 4 | POM_INCEPTION_YEAR=2016 5 | 6 | POM_URL=http://lachlanmckee.net/gsonpath/ 7 | POM_SCM_URL=scm:git@github.com:LachlanMcKee/gsonpath.git 8 | POM_SCM_CONNECTION=scm:git@github.com:LachlanMcKee/gsonpath.git 9 | POM_SCM_DEV_CONNECTION=scm:git@github.com:LachlanMcKee/gsonpath.git 10 | 11 | POM_LICENCE_NAME=MIT License 12 | POM_LICENCE_URL=http://www.opensource.org/licenses/mit-license.php 13 | POM_LICENCE_DIST=repo 14 | 15 | POM_DEVELOPER_ID=lachlanmckee 16 | POM_DEVELOPER_NAME=Lachlan McKee -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/array/ArrayExample.java: -------------------------------------------------------------------------------- 1 | package gsonpath.array; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | class ArrayExample { 8 | @SerializedName("test1[1]") 9 | int plainArray; 10 | 11 | @SerializedName("test2[2].child") 12 | int arrayWithNestedObject; 13 | 14 | @SerializedName("test2[2].child2") 15 | int arrayWithNestedObject2; 16 | 17 | @SerializedName("test3[3].child[1]") 18 | int arrayWithNestedArray; 19 | 20 | @SerializedName("test4.child[1]") 21 | int objectWithNestedArray; 22 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/custom_adapter_annotation/CustomAutoGsonAdapter.java: -------------------------------------------------------------------------------- 1 | package generator.standard.custom_adapter_annotation; 2 | 3 | import com.google.gson.FieldNamingPolicy; 4 | import gsonpath.GsonFieldValidationType; 5 | import gsonpath.annotation.AutoGsonAdapter; 6 | 7 | @AutoGsonAdapter( 8 | flattenDelimiter = '$', 9 | serializeNulls = true, 10 | ignoreNonAnnotatedFields = true, 11 | fieldNamingPolicy = FieldNamingPolicy.LOWER_CASE_WITH_DASHES, 12 | fieldValidationType = GsonFieldValidationType.VALIDATE_ALL_EXCEPT_NULLABLE 13 | ) 14 | public @interface CustomAutoGsonAdapter { 15 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/extension/annotation/IntRange.java: -------------------------------------------------------------------------------- 1 | package gsonpath.extension.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.Target; 6 | 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | @Retention(RUNTIME) 10 | @Target({ElementType.FIELD, ElementType.METHOD}) 11 | public @interface IntRange { 12 | /** 13 | * Smallest value, inclusive 14 | */ 15 | long from() default Long.MIN_VALUE; 16 | 17 | /** 18 | * Largest value, inclusive 19 | */ 20 | long to() default Long.MAX_VALUE; 21 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/field_policy/validate_explicit_non_null/TestValidateExplicitNonNull.java: -------------------------------------------------------------------------------- 1 | package generator.standard.field_policy.validate_explicit_non_null; 2 | 3 | import gsonpath.GsonFieldValidationType; 4 | import gsonpath.NonNull; 5 | import gsonpath.annotation.AutoGsonAdapter; 6 | 7 | @AutoGsonAdapter(fieldValidationType = GsonFieldValidationType.VALIDATE_EXPLICIT_NON_NULL) 8 | public class TestValidateExplicitNonNull { 9 | @NonNull 10 | public Integer mandatory1; 11 | @NonNull 12 | public Integer mandatory2; 13 | public int mandatory3; 14 | 15 | public Integer optional1; 16 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/annotation/GsonSubtype.java: -------------------------------------------------------------------------------- 1 | package gsonpath.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Allows a developer to mark a gson field as heterogenous, and exposes the ability to map specific types to a value value 10 | * that is found within the field name defined within the model being deserialized. 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.TYPE) 14 | public @interface GsonSubtype { 15 | String[] jsonKeys(); 16 | } 17 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/interf/inheritance/TestUsingInheritance.java: -------------------------------------------------------------------------------- 1 | package generator.interf.inheritance; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.NonNull; 5 | import gsonpath.annotation.AutoGsonAdapter; 6 | 7 | @AutoGsonAdapter 8 | public interface TestUsingInheritance extends TestUsingInheritanceBase { 9 | // 10 | // We remove the old SerializedName and add a non-null override 11 | // 12 | @NonNull 13 | Integer getValue1(); 14 | 15 | // We add a new SerializedName when non existed there before. 16 | @SerializedName("Json1.Nest2") 17 | Integer getValue2(); 18 | } -------------------------------------------------------------------------------- /sample/src/main/java/android/support/annotation/IntRange.java: -------------------------------------------------------------------------------- 1 | package android.support.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.Target; 5 | 6 | import static java.lang.annotation.ElementType.*; 7 | import static java.lang.annotation.RetentionPolicy.SOURCE; 8 | 9 | @Retention(SOURCE) 10 | @Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE, ANNOTATION_TYPE}) 11 | public @interface IntRange { 12 | /** 13 | * Smallest value, inclusive 14 | */ 15 | long from() default Long.MIN_VALUE; 16 | 17 | /** 18 | * Largest value, inclusive 19 | */ 20 | long to() default Long.MAX_VALUE; 21 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/array/TestArray.java: -------------------------------------------------------------------------------- 1 | package generator.standard.array; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | @AutoGsonAdapter 7 | class TestArray { 8 | @SerializedName("test1[1]") 9 | int plainArray; 10 | 11 | @SerializedName("test2[2].child") 12 | int arrayWithNestedObject; 13 | 14 | @SerializedName("test2[2].child2") 15 | int arrayWithNestedObject2; 16 | 17 | @SerializedName("test3[3].child[1]") 18 | int arrayWithNestedArray; 19 | 20 | @SerializedName("test4.child[1]") 21 | int objectWithNestedArray; 22 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/field_policy/no_validation/TestNoValidation.java: -------------------------------------------------------------------------------- 1 | package generator.standard.field_policy.no_validation; 2 | 3 | import gsonpath.GsonFieldValidationType; 4 | import gsonpath.NonNull; 5 | import gsonpath.Nullable; 6 | import gsonpath.annotation.AutoGsonAdapter; 7 | 8 | @AutoGsonAdapter(fieldValidationType = GsonFieldValidationType.NO_VALIDATION) 9 | public class TestNoValidation { 10 | @NonNull // This annotation is not used for validation purposes 11 | public Integer optional1; 12 | @Nullable // This annotation is not used for validation purposes 13 | public Integer optional2; 14 | 15 | public int optional3; 16 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/extension/annotation/FlattenJson.java: -------------------------------------------------------------------------------- 1 | package gsonpath.extension.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Specifies that the JSON object found for this field should be 7 | * flattened into a String. 8 | *

9 | * For example, given the following JSON: 10 | *

11 |  * {
12 |  *      'value1': 1,
13 |  *      'value2': 2
14 |  * }
15 |  * 
16 | * The following String is returned through the JsonParser: 17 | *

18 | * "{'value1': 1, 'value2': 2}" 19 | */ 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.FIELD, ElementType.METHOD}) 22 | @Inherited 23 | public @interface FlattenJson { 24 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/failures/TypesList_TooManyGsonSubtypeGetters.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.failures; 2 | 3 | import gsonpath.annotation.GsonSubtype; 4 | import gsonpath.annotation.GsonSubtypeGetter; 5 | 6 | @GsonSubtype( 7 | jsonKeys = {"type"} 8 | ) 9 | public class TypesList_TooManyGsonSubtypeGetters { 10 | @GsonSubtypeGetter 11 | static Class getSubType1(boolean type) { 12 | return null; 13 | } 14 | 15 | @GsonSubtypeGetter 16 | static Class getSubType2(boolean type) { 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/adapter/properties/AutoGsonAdapterProperties.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.adapter.properties 2 | 3 | import com.google.gson.FieldNamingPolicy 4 | import gsonpath.GsonFieldValidationType 5 | import gsonpath.annotation.PathSubstitution 6 | 7 | data class AutoGsonAdapterProperties( 8 | val fieldsRequireAnnotation: Boolean, 9 | val flattenDelimiter: Char, 10 | val serializeNulls: Boolean, 11 | val rootField: String, 12 | val gsonFieldValidationType: GsonFieldValidationType, 13 | val gsonFieldNamingPolicy: FieldNamingPolicy, 14 | val pathSubstitutions: List) 15 | -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/annotation/NestedJson.java: -------------------------------------------------------------------------------- 1 | package gsonpath.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Used to reduce SerializedName repetition. This is especially helpful when duplicating jsonpath numerous times. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) 13 | public @interface NestedJson { 14 | /** 15 | * @return the path of the nesting. Must be delimited by the correct character. 16 | */ 17 | String value(); 18 | } 19 | -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/array/ArrayTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.array 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class ArrayTest { 8 | 9 | @Test 10 | fun testArray() { 11 | assertGeneratedContent(TestCriteria("generator/standard/array", 12 | absoluteSourceNames = listOf("generator/standard/TestGsonTypeFactory.java"), 13 | relativeSourceNames = listOf("TestArray.java"), 14 | relativeGeneratedNames = listOf("TestArray_GsonTypeAdapter.java") 15 | )) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/indirectly_annotated/IndirectlyAnnotatedSubType.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.indirectly_annotated; 2 | 3 | import gsonpath.annotation.GsonSubtypeGetter; 4 | 5 | @IndirectSubType 6 | public abstract class IndirectlyAnnotatedSubType { 7 | @GsonSubtypeGetter 8 | static Class getSubType1(boolean type) { 9 | return null; 10 | } 11 | 12 | String name; 13 | 14 | public class Type1 extends IndirectlyAnnotatedSubType { 15 | int intTest; 16 | } 17 | 18 | public class Type2 extends IndirectlyAnnotatedSubType { 19 | double doubleTest; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/adapter/properties/PropertyFetcher.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.adapter.properties 2 | 3 | import gsonpath.ProcessingException 4 | import javax.lang.model.element.Element 5 | 6 | class PropertyFetcher(private val adapterElement: Element) { 7 | 8 | fun getProperty( 9 | propertyName: String, 10 | adapterArray: Array, 11 | factoryProperty: T 12 | ): T { 13 | if (adapterArray.size > 1) { 14 | throw ProcessingException("$propertyName should never have more than one element", adapterElement) 15 | } 16 | 17 | return adapterArray.firstOrNull() ?: factoryProperty 18 | } 19 | } -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/adapter/standard/extension/range/intrange/IntRangeModel.java: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.extension.range.intrange; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | public interface IntRangeModel { 6 | 7 | interface BaseModel { 8 | T getValue(); 9 | } 10 | 11 | @AutoGsonAdapter 12 | interface IntModel extends BaseModel { 13 | @android.support.annotation.IntRange(from = 0, to = 5) 14 | Integer getValue(); 15 | } 16 | 17 | @AutoGsonAdapter 18 | interface LongModel extends BaseModel { 19 | @gsonpath.extension.annotation.IntRange(from = 0, to = 5) 20 | Long getValue(); 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply from: "${project.rootDir}/scripts/jacoco-setup.gradle" 3 | apply from: "${project.rootDir}/scripts/clean-util.gradle" 4 | 5 | buildscript { 6 | repositories { 7 | mavenCentral() 8 | } 9 | dependencies { 10 | classpath 'com.vanniktech:gradle-maven-publish-plugin:0.7.0' 11 | } 12 | } 13 | 14 | apply plugin: "com.vanniktech.maven.publish" 15 | 16 | targetCompatibility = JavaVersion.VERSION_1_8 17 | sourceCompatibility = JavaVersion.VERSION_1_8 18 | 19 | dependencies { 20 | compile fileTree(dir: 'libs', include: ['*.jar']) 21 | compile "com.google.code.gson:gson:$gson_version" 22 | 23 | testCompile "junit:junit:$junit_version" 24 | } 25 | -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/generated/StoreModel.java: -------------------------------------------------------------------------------- 1 | package gsonpath.generated; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | 6 | import java.util.List; 7 | 8 | @AutoGsonAdapter(rootField = "store") 9 | class StoreModel { 10 | @SerializedName("book") 11 | List bookList; 12 | 13 | @SerializedName("bicycle.color") 14 | String bikeColour; 15 | 16 | @SerializedName("bicycle.price") 17 | double bikePrice; 18 | 19 | @AutoGsonAdapter 20 | static class BookModel { 21 | public String category; 22 | public String author; 23 | public String title; 24 | public double price; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/PackagePrivateTypeAdapterLoader.java: -------------------------------------------------------------------------------- 1 | package generator.factory; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.TypeAdapterFactory; 6 | import com.google.gson.reflect.TypeToken; 7 | 8 | import java.lang.Override; 9 | 10 | public final class PackagePrivateTypeAdapterLoader implements TypeAdapterFactory { 11 | @Override 12 | public TypeAdapter create(Gson gson, TypeToken type) { 13 | Class rawType = type.getRawType(); 14 | if (rawType.equals(TestLoaderSource.class)) { 15 | return new TestLoaderSource_GsonTypeAdapter(gson); 16 | 17 | } 18 | 19 | return null; 20 | } 21 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/adapter/read/ReadParams.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.adapter.read 2 | 3 | import com.squareup.javapoet.ClassName 4 | import gsonpath.adapter.standard.model.GsonArray 5 | import gsonpath.adapter.standard.model.GsonField 6 | import gsonpath.adapter.standard.model.GsonObject 7 | 8 | data class ReadParams( 9 | val baseElement: ClassName, 10 | val concreteElement: ClassName, 11 | val requiresConstructorInjection: Boolean, 12 | val mandatoryFields: List, 13 | val rootElements: GsonObject, 14 | val flattenedFields: List, 15 | val objectIndexes: List, 16 | val arrayIndexes: List 17 | ) -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/dependencies/Dependencies.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.dependencies 2 | 3 | import gsonpath.adapter.common.SubTypeMetadataFactory 4 | import gsonpath.adapter.standard.adapter.StandardGsonAdapterGenerator 5 | import gsonpath.adapter.standard.factory.TypeAdapterFactoryGenerator 6 | import gsonpath.adapter.enums.EnumGsonAdapterGenerator 7 | import gsonpath.util.FileWriter 8 | 9 | data class Dependencies( 10 | val standardGsonAdapterGenerator: StandardGsonAdapterGenerator, 11 | val fileWriter: FileWriter, 12 | val typeAdapterFactoryGenerator: TypeAdapterFactoryGenerator, 13 | val subTypeMetadataFactory: SubTypeMetadataFactory, 14 | val enumGsonAdapterGenerator: EnumGsonAdapterGenerator) -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/adapter/AdapterModelMetadata.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.adapter 2 | 3 | import com.squareup.javapoet.ClassName 4 | import gsonpath.adapter.standard.adapter.read.ReadParams 5 | import gsonpath.adapter.standard.adapter.write.WriteParams 6 | import gsonpath.adapter.standard.model.GsonField 7 | import gsonpath.adapter.standard.model.GsonObject 8 | 9 | data class AdapterModelMetadata( 10 | val modelClassName: ClassName, 11 | val adapterGenericTypeClassNames: List, 12 | val adapterClassName: ClassName, 13 | val isModelInterface: Boolean, 14 | val rootGsonObject: GsonObject, 15 | val readParams: ReadParams, 16 | val writeParams: WriteParams 17 | ) -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/adapter/standard/extension/invalid/InvalidModel.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.extension.invalid 2 | 3 | import gsonpath.GsonFieldValidationType 4 | import gsonpath.annotation.AutoGsonAdapter 5 | import gsonpath.extension.annotation.RemoveInvalidElements 6 | 7 | interface InvalidModel { 8 | @AutoGsonAdapter 9 | interface ArrayModel { 10 | @get:RemoveInvalidElements 11 | val value: Array 12 | } 13 | 14 | @AutoGsonAdapter 15 | interface CollectionModel { 16 | @get:RemoveInvalidElements 17 | val value: Collection 18 | } 19 | 20 | @AutoGsonAdapter(fieldValidationType = [GsonFieldValidationType.VALIDATE_ALL_EXCEPT_NULLABLE]) 21 | data class Data(val text: String) 22 | } 23 | -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/util/MethodSpecExt.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.util 2 | 3 | import com.squareup.javapoet.CodeBlock 4 | import com.squareup.javapoet.MethodSpec 5 | import javax.lang.model.element.Modifier 6 | 7 | object MethodSpecExt { 8 | fun overrideMethodBuilder(name: String): MethodSpec.Builder { 9 | return MethodSpec.methodBuilder(name) 10 | .addAnnotation(Override::class.java) 11 | .addModifiers(Modifier.PUBLIC) 12 | } 13 | } 14 | 15 | fun MethodSpec.Builder.code(func: CodeBlock.Builder.() -> Unit): MethodSpec.Builder { 16 | return addCode(CodeBlock.builder().applyAndBuild(func)) 17 | } 18 | 19 | fun MethodSpec.Builder.applyAndBuild(func: MethodSpec.Builder.() -> Unit): MethodSpec { 20 | return apply(func).build() 21 | } -------------------------------------------------------------------------------- /sample/src/test/resources/Polymorphism_type_is_null.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | { 4 | "type": null, 5 | "name": "Type1 Example 1", 6 | "intTest": 1 7 | }, 8 | { 9 | "type": "type1", 10 | "name": "Type1 Example 2", 11 | "intTest": 2 12 | }, 13 | { 14 | "type": "type2", 15 | "name": "Type2 Example 1", 16 | "doubleTest": 1.0 17 | }, 18 | { 19 | "type": "type3", 20 | "name": "Type3 Example 1", 21 | "stringTest": "123" 22 | }, 23 | { 24 | "type": "unexpected_type", 25 | "name": "Type3 Example 1", 26 | "stringTest": "123" 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/util/TypeSpecExt.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.util 2 | 3 | import com.squareup.javapoet.JavaFile 4 | import com.squareup.javapoet.TypeSpec 5 | import gsonpath.ProcessingException 6 | import gsonpath.util.FileWriter 7 | import java.io.IOException 8 | 9 | fun TypeSpec.Builder.writeFile( 10 | fileWriter: FileWriter, 11 | packageName: String, 12 | fileBuiltFunc: (builder: JavaFile.Builder) -> Unit = {}) { 13 | 14 | try { 15 | JavaFile.builder(packageName, build()).apply { 16 | fileBuiltFunc(this) 17 | build().writeTo(fileWriter.filer) 18 | } 19 | 20 | } catch (e: IOException) { 21 | throw ProcessingException("Error while writing javapoet file: ${e.message}") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/GsonPathTypeAdapterFactory.java: -------------------------------------------------------------------------------- 1 | package gsonpath; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.TypeAdapterFactory; 6 | import com.google.gson.reflect.TypeToken; 7 | import gsonpath.internal.GsonSafeListTypeAdapterFactory; 8 | 9 | /** 10 | * Adds serialization/deserialization handling for GsonPath specific types to Gson. 11 | */ 12 | public final class GsonPathTypeAdapterFactory implements TypeAdapterFactory { 13 | private final GsonSafeListTypeAdapterFactory safeListFactory = 14 | new GsonSafeListTypeAdapterFactory(); 15 | 16 | @Override 17 | public TypeAdapter create(Gson gson, TypeToken typeToken) { 18 | return safeListFactory.create(gson, typeToken); 19 | } 20 | } -------------------------------------------------------------------------------- /sample/src/test/resources/SealedClassSample.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | { 4 | "type": "type1", 5 | "common": { 6 | "name": "Type1 Example" 7 | }, 8 | "specific": { 9 | "intTest": 1 10 | } 11 | }, 12 | { 13 | "type": "type2", 14 | "common": { 15 | "name": "Type2 Example" 16 | }, 17 | "specific": { 18 | "doubleTest": 1.0 19 | } 20 | }, 21 | { 22 | "type": "type3", 23 | "common": { 24 | "name": "Type3 Example" 25 | }, 26 | "specific": { 27 | "stringTest": "123" 28 | } 29 | }, 30 | { 31 | "common": { 32 | "name": "Type3 Example" 33 | }, 34 | "specific": { 35 | "stringTest": "123" 36 | } 37 | } 38 | ] 39 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/interf/valid/PackagePrivateTypeAdapterLoader.java: -------------------------------------------------------------------------------- 1 | package generator.interf.valid; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.TypeAdapterFactory; 6 | import com.google.gson.reflect.TypeToken; 7 | import java.lang.Class; 8 | import java.lang.Override; 9 | 10 | public final class PackagePrivateTypeAdapterLoader implements TypeAdapterFactory { 11 | @Override 12 | public TypeAdapter create(Gson gson, TypeToken type) { 13 | Class rawType = type.getRawType(); 14 | if (rawType.equals(TestValidInterface_GsonPathModel.class) || rawType.equals(TestValidInterface.class)) { 15 | return new TestValidInterface_GsonTypeAdapter(gson); 16 | } 17 | 18 | return null; 19 | } 20 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/AdapterFactory.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter 2 | 3 | import com.squareup.javapoet.ClassName 4 | import gsonpath.LazyFactoryMetadata 5 | import gsonpath.dependencies.Dependencies 6 | import gsonpath.util.Logger 7 | import javax.annotation.processing.RoundEnvironment 8 | import javax.lang.model.element.TypeElement 9 | 10 | interface AdapterFactory { 11 | fun generateGsonAdapters( 12 | env: RoundEnvironment, 13 | logger: Logger, 14 | lazyFactoryMetadata: LazyFactoryMetadata, 15 | annotations: Set, 16 | dependencies: Dependencies): List 17 | } 18 | 19 | class AdapterGenerationResult( 20 | val adapterGenericTypeClassNames: Array, 21 | val adapterClassName: ClassName) -------------------------------------------------------------------------------- /library-kt/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "java" 2 | apply plugin: "kotlin" 3 | apply from: "${project.rootDir}/scripts/jacoco-setup.gradle" 4 | apply from: "${project.rootDir}/scripts/clean-util.gradle" 5 | 6 | buildscript { 7 | repositories { 8 | mavenCentral() 9 | } 10 | dependencies { 11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 | classpath "com.vanniktech:gradle-maven-publish-plugin:0.7.0" 13 | } 14 | } 15 | 16 | apply plugin: "com.vanniktech.maven.publish" 17 | 18 | targetCompatibility = JavaVersion.VERSION_1_8 19 | sourceCompatibility = JavaVersion.VERSION_1_8 20 | 21 | dependencies { 22 | compile project(":library") 23 | compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 24 | 25 | testCompile "junit:junit:$junit_version" 26 | } 27 | -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/adapter/enums/EnumExample.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.enums 2 | 3 | import com.google.gson.FieldNamingPolicy 4 | import gsonpath.annotation.AutoGsonAdapter 5 | import gsonpath.annotation.EnumGsonAdapter 6 | 7 | @AutoGsonAdapter 8 | class EnumExample( 9 | val values: Array, 10 | val valuesWithDefault: Array 11 | ) { 12 | 13 | @EnumGsonAdapter(fieldNamingPolicy = [FieldNamingPolicy.LOWER_CASE_WITH_DASHES], ignoreDefaultValue = true) 14 | enum class EnumValue { 15 | VALUE1, 16 | VALUE_2, 17 | VALUE_3_AND_4 18 | } 19 | 20 | @EnumGsonAdapter(fieldNamingPolicy = [FieldNamingPolicy.LOWER_CASE_WITH_DASHES]) 21 | enum class EnumValueWithDefault { 22 | @EnumGsonAdapter.DefaultValue 23 | VALUE1 24 | } 25 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/nesting/NestedClassTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.nesting 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class NestedClassTest { 8 | @Test 9 | fun testNestedClasses() { 10 | assertGeneratedContent(TestCriteria("generator/standard/nested_class", 11 | 12 | absoluteSourceNames = listOf( 13 | "generator/standard/TestGsonTypeFactory.java"), 14 | 15 | relativeSourceNames = listOf( 16 | "TestNestedClass.java"), 17 | 18 | relativeGeneratedNames = listOf( 19 | "TestNestedClass_Nested_GsonTypeAdapter.java") 20 | )) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/util/Logger.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.util 2 | 3 | import javax.annotation.processing.ProcessingEnvironment 4 | import javax.lang.model.element.Element 5 | import javax.tools.Diagnostic 6 | 7 | class Logger(private val processingEnv: ProcessingEnvironment) { 8 | 9 | fun printMessage(message: String) { 10 | println(LOG_PREFIX + message) 11 | } 12 | 13 | fun printError(message: String, element: Element? = null) { 14 | if (element != null) { 15 | processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, LOG_PREFIX + message, element) 16 | } else { 17 | processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, LOG_PREFIX + message) 18 | } 19 | } 20 | 21 | companion object { 22 | private const val LOG_PREFIX = "Gson Path: " 23 | } 24 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/fields/FieldAnnotationsTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.fields 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class FieldAnnotationsTest { 8 | 9 | @Test 10 | fun testExcludeFields() { 11 | assertGeneratedContent(TestCriteria("generator/standard/field_annotations/exclude", 12 | 13 | absoluteSourceNames = listOf( 14 | "generator/standard/TestGsonTypeFactory.java"), 15 | 16 | relativeSourceNames = listOf( 17 | "TestExclude.java"), 18 | 19 | relativeGeneratedNames = listOf( 20 | "TestExclude_GsonTypeAdapter.java") 21 | )) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/extension/annotation/Size.java: -------------------------------------------------------------------------------- 1 | package gsonpath.extension.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.Target; 6 | 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | @Retention(RUNTIME) 10 | @Target({ElementType.FIELD, ElementType.METHOD}) 11 | public @interface Size { 12 | /** 13 | * An exact size (or -1 if not specified) 14 | */ 15 | long value() default -1; 16 | 17 | /** 18 | * A minimum size, inclusive 19 | */ 20 | long min() default Long.MIN_VALUE; 21 | 22 | /** 23 | * A maximum size, inclusive 24 | */ 25 | long max() default Long.MAX_VALUE; 26 | 27 | /** 28 | * The size must be a multiple of this factor 29 | */ 30 | long multiple() default 1; 31 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/properties/SerializeNullsTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.properties 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class SerializeNullsTest { 8 | 9 | @Test 10 | fun testSerializeNulls() { 11 | assertGeneratedContent(TestCriteria("generator/standard/serialize_nulls", 12 | 13 | absoluteSourceNames = listOf( 14 | "generator/standard/TestGsonTypeFactory.java"), 15 | 16 | relativeSourceNames = listOf( 17 | "TestSerializeNulls.java"), 18 | 19 | relativeGeneratedNames = listOf( 20 | "TestSerializeNulls_GsonTypeAdapter.java") 21 | )) 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/extension/invalid/immutable/TestImmutableRemoveInvalidElements.java: -------------------------------------------------------------------------------- 1 | package generator.standard.invalid.immutable; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | import gsonpath.extension.annotation.RemoveInvalidElements; 5 | 6 | import java.util.List; 7 | 8 | @AutoGsonAdapter 9 | public class TestImmutableRemoveInvalidElements { 10 | @RemoveInvalidElements 11 | private String[] value1; 12 | 13 | @RemoveInvalidElements 14 | private List value2; 15 | 16 | public TestImmutableRemoveInvalidElements(String[] value1, List value2) { 17 | this.value1 = value1; 18 | this.value2 = value2; 19 | } 20 | 21 | public String[] getValue1() { 22 | return value1; 23 | } 24 | 25 | public List getValue2() { 26 | return value2; 27 | } 28 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/misc/UsingConstructorTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.misc 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class UsingConstructorTest { 8 | @Test 9 | fun testDataClassJavaRepresentation() { 10 | assertGeneratedContent(TestCriteria("generator/standard/using_constructor/valid", 11 | 12 | absoluteSourceNames = listOf( 13 | "generator/standard/TestGsonTypeFactory.java"), 14 | 15 | relativeSourceNames = listOf( 16 | "ValidConstructorTest.java"), 17 | 18 | relativeGeneratedNames = listOf( 19 | "ValidConstructorTest_GsonTypeAdapter.java") 20 | )) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /compiler/base/build.gradle: -------------------------------------------------------------------------------- 1 | import org.gradle.internal.jvm.Jvm 2 | 3 | apply plugin: 'java' 4 | apply plugin: "kotlin" 5 | apply from: "${project.rootDir}/scripts/clean-util.gradle" 6 | 7 | buildscript { 8 | repositories { 9 | mavenCentral() 10 | } 11 | dependencies { 12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 13 | classpath 'com.vanniktech:gradle-maven-publish-plugin:0.7.0' 14 | } 15 | } 16 | 17 | apply plugin: "com.vanniktech.maven.publish" 18 | 19 | targetCompatibility = JavaVersion.VERSION_1_8 20 | sourceCompatibility = JavaVersion.VERSION_1_8 21 | 22 | dependencies { 23 | compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 24 | compile "com.squareup:javapoet:$javapoet_version" 25 | compile files(Jvm.current().getToolsJar()) 26 | 27 | testCompile "junit:junit:$junit_version" 28 | } 29 | -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/misc/InheritanceTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.misc 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class InheritanceTest { 8 | @Test 9 | fun testInheritance() { 10 | assertGeneratedContent(TestCriteria("generator/standard/inheritance", 11 | 12 | absoluteSourceNames = listOf( 13 | "generator/standard/TestGsonTypeFactory.java"), 14 | 15 | relativeSourceNames = listOf( 16 | "TestInheritanceBase.java", 17 | "TestInheritance.java"), 18 | 19 | relativeGeneratedNames = listOf( 20 | "TestInheritance_GsonTypeAdapter.java") 21 | )) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/annotation/EnumGsonAdapter.java: -------------------------------------------------------------------------------- 1 | package gsonpath.annotation; 2 | 3 | import com.google.gson.FieldNamingPolicy; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Target(ElementType.TYPE) 12 | public @interface EnumGsonAdapter { 13 | FieldNamingPolicy[] fieldNamingPolicy() default {}; 14 | 15 | /** 16 | * Specifies whether a default value needs to be specified. 17 | * If this is set to false, the processor will throw an error if no default is provided. 18 | */ 19 | boolean ignoreDefaultValue() default false; 20 | 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target(ElementType.FIELD) 23 | @interface DefaultValue { 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sample/src/main/java/android/support/annotation/Size.java: -------------------------------------------------------------------------------- 1 | package android.support.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.Target; 5 | 6 | import static java.lang.annotation.ElementType.*; 7 | import static java.lang.annotation.RetentionPolicy.CLASS; 8 | 9 | @Retention(CLASS) 10 | @Target({PARAMETER, LOCAL_VARIABLE, METHOD, FIELD, ANNOTATION_TYPE}) 11 | public @interface Size { 12 | /** 13 | * An exact size (or -1 if not specified) 14 | */ 15 | long value() default -1; 16 | 17 | /** 18 | * A minimum size, inclusive 19 | */ 20 | long min() default Long.MIN_VALUE; 21 | 22 | /** 23 | * A maximum size, inclusive 24 | */ 25 | long max() default Long.MAX_VALUE; 26 | 27 | /** 28 | * The size must be a multiple of this factor 29 | */ 30 | long multiple() default 1; 31 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/custom_serialized_name_annotation/TestCustomSerializedNameModel.java: -------------------------------------------------------------------------------- 1 | package generator.standard.custom_serialized_name_annotation; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | import gsonpath.annotation.NestedJson; 6 | 7 | @AutoGsonAdapter(ignoreNonAnnotatedFields = true) 8 | public class TestCustomSerializedNameModel { 9 | @GsonNest 10 | String value1; 11 | 12 | @GsonNest 13 | @SerializedName("value2") 14 | String valueX; 15 | 16 | @GsonNest 17 | @SerializedName("second.") 18 | String value3; 19 | 20 | @NestedJson("nest") 21 | String value1b; 22 | 23 | @NestedJson("nest") 24 | @SerializedName("value2b") 25 | String valueXb; 26 | 27 | @NestedJson("nest") 28 | @SerializedName("second.") 29 | String value3b; 30 | } -------------------------------------------------------------------------------- /sample/src/test/resources/Polymorphism_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | { 4 | "type": "type1", 5 | "name": "Type1 Example 1", 6 | "intTest": 1 7 | }, 8 | { 9 | "type": "type1", 10 | "name": "Type1 Example 2", 11 | "intTest": 2 12 | }, 13 | { 14 | "type": "type2", 15 | "name": "Type2 Example 1", 16 | "doubleTest": 1.0 17 | }, 18 | { 19 | "type": "type3", 20 | "name": "Type3 Example 1", 21 | "stringTest": "123" 22 | }, 23 | { 24 | "type": null, 25 | "name": "TypeNull Example 1" 26 | }, 27 | { 28 | "type": "unexpected_type", 29 | "name": "Type3 Example 1", 30 | "stringTest": "123" 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/fields/UseGetterAnnotationTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.fields 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class UseGetterAnnotationTest { 8 | @Test 9 | fun testDataClassJavaRepresentation() { 10 | assertGeneratedContent(TestCriteria("generator/standard/use_getter_annotation/", 11 | 12 | absoluteSourceNames = listOf( 13 | "generator/standard/TestGsonTypeFactory.java"), 14 | 15 | relativeSourceNames = listOf( 16 | "UseGetterAnnotationTest.java"), 17 | 18 | relativeGeneratedNames = listOf( 19 | "UseGetterAnnotationTest_Implementation_GsonTypeAdapter.java") 20 | )) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/source2/PackagePrivateTypeAdapterLoader.java: -------------------------------------------------------------------------------- 1 | package generator.factory.source2; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.TypeAdapterFactory; 6 | import com.google.gson.reflect.TypeToken; 7 | import java.lang.Class; 8 | import java.lang.Override; 9 | 10 | public final class PackagePrivateTypeAdapterLoader implements TypeAdapterFactory { 11 | @Override 12 | public TypeAdapter create(Gson gson, TypeToken type) { 13 | Class rawType = type.getRawType(); 14 | if (rawType.equals(TestLoaderSource.class)) { 15 | return new TestLoaderSource_GsonTypeAdapter(gson); 16 | 17 | } else if (rawType.equals(TestLoaderSource2.class)) { 18 | return new TestLoaderSource2_GsonTypeAdapter(gson); 19 | } 20 | 21 | return null; 22 | } 23 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/source3/PackagePrivateTypeAdapterLoader.java: -------------------------------------------------------------------------------- 1 | package generator.factory.source3; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.TypeAdapterFactory; 6 | import com.google.gson.reflect.TypeToken; 7 | import java.lang.Class; 8 | import java.lang.Override; 9 | 10 | public final class PackagePrivateTypeAdapterLoader implements TypeAdapterFactory { 11 | @Override 12 | public TypeAdapter create(Gson gson, TypeToken type) { 13 | Class rawType = type.getRawType(); 14 | if (rawType.equals(TestLoaderSource.class)) { 15 | return new TestLoaderSource_GsonTypeAdapter(gson); 16 | 17 | } else if (rawType.equals(TestLoaderSource.Inner.class)) { 18 | return new TestLoaderSource_Inner_GsonTypeAdapter(gson); 19 | } 20 | 21 | return null; 22 | } 23 | } -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/util/ElementExt.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.util 2 | 3 | import javax.lang.model.element.Element 4 | 5 | /** 6 | * Fetches the annotation from the element directly. 7 | * 8 | * Failing that it attempts to find any annotations that are annotated with the annotation type. The method then returns 9 | * that annotation. This allows easy annotation reuse. 10 | */ 11 | fun Element.getAnnotationEx(annotationType: Class): A? { 12 | val immediateAnnotation = getAnnotation(annotationType) 13 | if (immediateAnnotation != null) { 14 | return immediateAnnotation 15 | } 16 | 17 | // See if there are any annotations that are themselves annotated by the annotation we want. 18 | return annotationMirrors 19 | .asSequence() 20 | .mapNotNull { it.annotationType.asElement().getAnnotation(annotationType) } 21 | .firstOrNull() 22 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/AdapterMethodBuilder.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter 2 | 3 | import com.google.gson.stream.JsonReader 4 | import com.google.gson.stream.JsonWriter 5 | import com.squareup.javapoet.TypeName 6 | import gsonpath.util.MethodSpecExt 7 | import java.io.IOException 8 | 9 | object AdapterMethodBuilder { 10 | fun createReadMethodBuilder(returnTypeName: TypeName) = MethodSpecExt.overrideMethodBuilder("readImpl").apply { 11 | returns(returnTypeName) 12 | addParameter(JsonReader::class.java, Constants.IN) 13 | addException(IOException::class.java) 14 | } 15 | 16 | fun createWriteMethodBuilder(writtenValueTypeName: TypeName) = MethodSpecExt.overrideMethodBuilder("writeImpl").apply { 17 | addParameter(JsonWriter::class.java, Constants.OUT) 18 | addParameter(writtenValueTypeName, Constants.VALUE) 19 | addException(IOException::class.java) 20 | } 21 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/nesting/GsonNestTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.nesting 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class GsonNestTest { 8 | @Test 9 | fun testCustomAutoGsonAdapterAnnotation() { 10 | assertGeneratedContent(TestCriteria("generator/standard/custom_serialized_name_annotation", 11 | 12 | absoluteSourceNames = listOf( 13 | "generator/standard/TestGsonTypeFactory.java"), 14 | 15 | relativeSourceNames = listOf( 16 | "GsonNest.java", 17 | "TestCustomSerializedNameModel.java"), 18 | 19 | relativeGeneratedNames = listOf( 20 | "TestCustomSerializedNameModel_GsonTypeAdapter.java") 21 | )) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /library-kt/src/main/java/gsonpath/GsonPathTypeAdapterFactoryKt.kt: -------------------------------------------------------------------------------- 1 | package gsonpath 2 | 3 | import com.google.gson.Gson 4 | import com.google.gson.TypeAdapter 5 | import com.google.gson.TypeAdapterFactory 6 | import com.google.gson.reflect.TypeToken 7 | import gsonpath.internal.GsonResultListTypeAdapterFactory 8 | 9 | /** 10 | * Adds serialization/deserialization handling for GsonPath specific types to Gson. 11 | * 12 | * This version of the class proxies to GsonPathTypeAdapterFactory, so it can be used as the sole factory. 13 | */ 14 | class GsonPathTypeAdapterFactoryKt : TypeAdapterFactory { 15 | override fun create(gson: Gson, type: TypeToken): TypeAdapter? { 16 | return gsonPathFactory.create(gson, type) ?: gsonResultListFactory.create(gson, type) 17 | } 18 | 19 | private val gsonPathFactory by lazy { GsonPathTypeAdapterFactory() } 20 | private val gsonResultListFactory by lazy { GsonResultListTypeAdapterFactory() } 21 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty # Required due to Xenial not working with oraclejdk8 2 | language: java 3 | 4 | notifications: 5 | email: false 6 | 7 | jdk: 8 | - oraclejdk8 9 | 10 | branches: 11 | only: 12 | - master 13 | - develop 14 | 15 | script: 16 | - ./gradlew check 17 | - ./gradlew sonarqube -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=lachlanmckee-github -Dsonar.login=$SONAR_TOKEN 18 | - ./gradlew integrationCodeCoverageReport 19 | - bash <(curl -s https://codecov.io/bash) -c -F integration 20 | - ./gradlew unitCodeCoverageReport 21 | - bash <(curl -s https://codecov.io/bash) -c -F unit_tests 22 | 23 | before_cache: 24 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 25 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ 26 | cache: 27 | directories: 28 | - $HOME/.gradle/caches/ 29 | - $HOME/.gradle/wrapper/ 30 | 31 | before_install: 32 | - chmod +x gradlew 33 | - chmod +x gradle/wrapper/gradle-wrapper.jar 34 | -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/errors/GsonErrorTestModel.java: -------------------------------------------------------------------------------- 1 | package gsonpath.errors; 2 | 3 | import gsonpath.GsonFieldValidationType; 4 | import gsonpath.GsonSafeList; 5 | import gsonpath.annotation.AutoGsonAdapter; 6 | import gsonpath.extension.annotation.Size; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @AutoGsonAdapter 12 | class GsonErrorTestModel { 13 | 14 | ValuesWrapper singleValue; 15 | 16 | List listValue; 17 | 18 | ValuesWrapper[] arrayValue; 19 | 20 | Map mapValue; 21 | 22 | @AutoGsonAdapter(fieldValidationType = GsonFieldValidationType.VALIDATE_ALL_EXCEPT_NULLABLE) 23 | static class ValuesWrapper { 24 | GsonSafeList values; 25 | } 26 | 27 | @AutoGsonAdapter(fieldValidationType = GsonFieldValidationType.VALIDATE_ALL_EXCEPT_NULLABLE) 28 | static class StrictTextModel { 29 | @Size(min = 1, max = 5) 30 | public String text; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/extension/annotation/FloatRange.java: -------------------------------------------------------------------------------- 1 | package gsonpath.extension.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.Target; 6 | 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | @Retention(RUNTIME) 10 | @Target({ElementType.FIELD, ElementType.METHOD}) 11 | public @interface FloatRange { 12 | /** 13 | * Smallest value. Whether it is inclusive or not is determined 14 | * by {@link #fromInclusive} 15 | */ 16 | double from() default Double.NEGATIVE_INFINITY; 17 | 18 | /** 19 | * Largest value. Whether it is inclusive or not is determined 20 | * by {@link #toInclusive} 21 | */ 22 | double to() default Double.POSITIVE_INFINITY; 23 | 24 | /** 25 | * Whether the from value is included in the range 26 | */ 27 | boolean fromInclusive() default true; 28 | 29 | /** 30 | * Whether the to value is included in the range 31 | */ 32 | boolean toInclusive() default true; 33 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/LazyFactoryMetadata.kt: -------------------------------------------------------------------------------- 1 | package gsonpath 2 | 3 | import gsonpath.adapter.util.ElementAndAnnotation 4 | import gsonpath.annotation.AutoGsonAdapterFactory 5 | import javax.lang.model.element.TypeElement 6 | 7 | class LazyFactoryMetadata( 8 | private val _elementAndAnnotation: ElementAndAnnotation?) { 9 | 10 | private val elementAndAnnotation: ElementAndAnnotation 11 | get() { 12 | return _elementAndAnnotation ?: throw ProcessingException("An interface annotated with" + 13 | " @AutoGsonAdapterFactory (that directly extends com.google.gson.TypeAdapterFactory) must exist " + 14 | "before the annotation processor can succeed. " + 15 | "See the AutoGsonAdapterFactory annotation for further details.") 16 | } 17 | 18 | val annotation: AutoGsonAdapterFactory 19 | get() = elementAndAnnotation.annotation 20 | 21 | val element: TypeElement 22 | get() = elementAndAnnotation.element 23 | } -------------------------------------------------------------------------------- /sample/src/test/java/gsonpath/adapter/standard/extension/invalid/InvalidTests.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.extension.invalid 2 | 3 | import gsonpath.TestUtil.executeFromJson 4 | import org.junit.Assert 5 | import org.junit.Test 6 | 7 | class InvalidTests { 8 | 9 | @Test 10 | fun testInvalidElementsRemoved() { 11 | assertValues("{value:[{'text': null}, {'text': 'a'}, {'text': null}, {'text': 'c'}, {'text': null}]}", 12 | InvalidModel.Data("a"), InvalidModel.Data("c")) 13 | } 14 | 15 | @Test 16 | fun testValuesEmptyWhenAllInvalid() { 17 | assertValues("{value:[{'text': null}, {'text': null}, {'text': null}]}") 18 | } 19 | 20 | private fun assertValues(jsonText: String, vararg expected: InvalidModel.Data) { 21 | Assert.assertArrayEquals(expected, 22 | executeFromJson(InvalidModel.ArrayModel::class.java, jsonText).value) 23 | 24 | Assert.assertEquals(expected.toList(), 25 | executeFromJson(InvalidModel.CollectionModel::class.java, jsonText).value) 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /sample/src/main/java/android/support/annotation/FloatRange.java: -------------------------------------------------------------------------------- 1 | package android.support.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.Target; 5 | 6 | import static java.lang.annotation.ElementType.*; 7 | import static java.lang.annotation.RetentionPolicy.CLASS; 8 | 9 | @Retention(CLASS) 10 | @Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE, ANNOTATION_TYPE}) 11 | public @interface FloatRange { 12 | /** 13 | * Smallest value. Whether it is inclusive or not is determined 14 | * by {@link #fromInclusive} 15 | */ 16 | double from() default Double.NEGATIVE_INFINITY; 17 | 18 | /** 19 | * Largest value. Whether it is inclusive or not is determined 20 | * by {@link #toInclusive} 21 | */ 22 | double to() default Double.POSITIVE_INFINITY; 23 | 24 | /** 25 | * Whether the from value is included in the range 26 | */ 27 | boolean fromInclusive() default true; 28 | 29 | /** 30 | * Whether the to value is included in the range 31 | */ 32 | boolean toInclusive() default true; 33 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/extension/ExtensionsLoader.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.extension 2 | 3 | import gsonpath.ProcessingException 4 | import gsonpath.compiler.GsonPathExtension 5 | import gsonpath.util.Logger 6 | import java.util.* 7 | 8 | object ExtensionsLoader { 9 | 10 | fun loadExtensions(logger: Logger): List { 11 | // Load any extensions that are also available at compile time. 12 | println() 13 | val extensions: List = 14 | try { 15 | ServiceLoader.load(GsonPathExtension::class.java, javaClass.classLoader).toList() 16 | 17 | } catch (t: Throwable) { 18 | throw ProcessingException("Failed to load one or more GsonPath extensions. Cause: ${t.message}") 19 | } 20 | 21 | // Print the extensions for auditing purposes. 22 | extensions.forEach { 23 | logger.printMessage("Extension found: " + it.extensionName) 24 | } 25 | 26 | return extensions 27 | } 28 | } -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/util/TypeSpecExt.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.util 2 | 3 | import com.squareup.javapoet.* 4 | import javax.lang.model.element.Modifier 5 | 6 | object TypeSpecExt { 7 | fun finalClassBuilder(name: String): TypeSpec.Builder { 8 | return TypeSpec.classBuilder(name) 9 | .addModifiers(Modifier.PUBLIC, Modifier.FINAL) 10 | } 11 | 12 | fun finalClassBuilder(className: ClassName): TypeSpec.Builder { 13 | return TypeSpec.classBuilder(className) 14 | .addModifiers(Modifier.PUBLIC, Modifier.FINAL) 15 | } 16 | } 17 | 18 | fun TypeSpec.Builder.field(name: String, type: TypeName, func: FieldSpec.Builder.() -> Unit) { 19 | addField(FieldSpec.builder(type, name).apply(func).build()) 20 | } 21 | 22 | fun TypeSpec.Builder.overrideMethod(name: String, func: MethodSpec.Builder.() -> Unit) { 23 | addMethod(MethodSpecExt.overrideMethodBuilder(name).applyAndBuild(func)) 24 | } 25 | 26 | fun TypeSpec.Builder.constructor(func: MethodSpec.Builder.() -> Unit) { 27 | addMethod(MethodSpec.constructorBuilder().applyAndBuild(func)) 28 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/GsonFieldValidationType.java: -------------------------------------------------------------------------------- 1 | package gsonpath; 2 | 3 | /** 4 | * Specifies what type of validation should be done during Gson parsing. 5 | *

6 | * If some form of validation is used, and a field does not pass the validation, an exception 7 | * will be thrown and the parser will not return a result. 8 | */ 9 | public enum GsonFieldValidationType { 10 | /** 11 | * No validation will be done on fields, regardless of whether they use 12 | * 'nullable' or 'nonnull' annotations. 13 | */ 14 | NO_VALIDATION, 15 | 16 | /** 17 | * All fields marked with non-null will be validated during parsing 18 | * if the field is not found, an exception will be thrown. 19 | *

20 | * Primitive fields will also be treated as non-null. If you want to 21 | * ensure that a primitive can be optional, make it boxed. 22 | */ 23 | VALIDATE_EXPLICIT_NON_NULL, 24 | 25 | /** 26 | * All fields will be validated unless they are marked with a 'nullable' 27 | * annotation. 28 | */ 29 | VALIDATE_ALL_EXCEPT_NULLABLE 30 | } 31 | -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/compiler/SharedFunctions.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.compiler 2 | 3 | import com.squareup.javapoet.ClassName 4 | import com.squareup.javapoet.TypeName 5 | 6 | val CLASS_NAME_STRING: ClassName = ClassName.get(String::class.java) 7 | 8 | fun createDefaultVariableValueForTypeName(typeName: TypeName) = when (typeName) { 9 | TypeName.INT, TypeName.BYTE, TypeName.SHORT -> "0" 10 | TypeName.LONG -> "0L" 11 | TypeName.FLOAT -> "0f" 12 | TypeName.DOUBLE -> "0d" 13 | TypeName.CHAR -> "'\\u0000'" 14 | TypeName.BOOLEAN -> "false" 15 | else -> "null" 16 | } 17 | 18 | fun generateClassName(className: ClassName, classNameSuffix: String): String { 19 | // 20 | // We need to ensure that nested classes are have include their parent class as part of the name. 21 | // Otherwise this could cause file name contention when other nested classes have the same name 22 | // 23 | val fileName = className.simpleNames().joinToString("_") 24 | 25 | // Make sure no '.' managed to sneak through! 26 | return fileName.replace(".", "_") + "_" + classNameSuffix 27 | } -------------------------------------------------------------------------------- /sample/src/test/resources/BookJson.json: -------------------------------------------------------------------------------- 1 | { 2 | "store": { 3 | "book": [ 4 | { 5 | "category": "reference", 6 | "author": "Nigel Rees", 7 | "title": "Sayings of the Century", 8 | "price": 8.95 9 | }, 10 | { 11 | "category": "fiction", 12 | "author": "Evelyn Waugh", 13 | "title": "Sword of Honour", 14 | "price": 12.99 15 | }, 16 | { 17 | "category": "fiction", 18 | "author": "Herman Melville", 19 | "title": "Moby Dick", 20 | "isbn": "0-553-21311-3", 21 | "price": 8.99 22 | }, 23 | { 24 | "category": "fiction", 25 | "author": "J. R. R. Tolkien", 26 | "title": "The Lord of the Rings", 27 | "isbn": "0-395-19395-8", 28 | "price": 22.99 29 | } 30 | ], 31 | "bicycle": { 32 | "color": "red", 33 | "price": 19.95 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Lachlan McKee 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/audit/AuditJsonReader.java: -------------------------------------------------------------------------------- 1 | package gsonpath.audit; 2 | 3 | import com.google.gson.stream.JsonReader; 4 | 5 | import java.io.Reader; 6 | 7 | /** 8 | * An implementation of the {@link JsonReader} that contains an audit log that records whenever a data-mapping 9 | * issue occurs. 10 | *

11 | * Currently a data-mapping issue occurs when: 12 | *

15 | */ 16 | public final class AuditJsonReader extends JsonReader { 17 | private AuditLog auditLog; 18 | 19 | public AuditJsonReader(Reader in) { 20 | super(in); 21 | this.auditLog = new AuditLog(); 22 | } 23 | 24 | /** 25 | * @return the audit log for the reader. 26 | */ 27 | public AuditLog getAuditLog() { 28 | return auditLog; 29 | } 30 | 31 | public static AuditLog getAuditLogFromReader(JsonReader reader) { 32 | if (reader instanceof AuditJsonReader) { 33 | return ((AuditJsonReader) reader).getAuditLog(); 34 | } else { 35 | return null; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sample/src/test/java/gsonpath/generated/StoreModelTest.java: -------------------------------------------------------------------------------- 1 | package gsonpath.generated; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import gsonpath.GsonPath; 6 | import gsonpath.TestGsonTypeFactory; 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | import java.io.InputStream; 11 | import java.io.InputStreamReader; 12 | 13 | public class StoreModelTest { 14 | @Test 15 | public void test() { 16 | GsonBuilder builder = new GsonBuilder(); 17 | builder.registerTypeAdapterFactory(GsonPath.createTypeAdapterFactory(TestGsonTypeFactory.class)); 18 | 19 | ClassLoader classLoader = ClassLoader.getSystemClassLoader(); 20 | InputStream resourceAsStream = classLoader.getResourceAsStream("BookJson.json"); 21 | 22 | Gson gson = builder.create(); 23 | StoreModel model = gson.fromJson(new InputStreamReader(resourceAsStream), StoreModel.class); 24 | 25 | Assert.assertEquals("red", model.bikeColour); 26 | Assert.assertEquals(4, model.bookList.size()); 27 | Assert.assertEquals("J. R. R. Tolkien", model.bookList.get(3).author); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/model/GsonModels.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.model 2 | 3 | import gsonpath.model.FieldInfo 4 | 5 | sealed class GsonModel 6 | sealed class GsonArrayElement : GsonModel() 7 | 8 | data class GsonField( 9 | val fieldIndex: Int, 10 | val fieldInfo: FieldInfo, 11 | val variableName: String, 12 | val jsonPath: String, 13 | val isRequired: Boolean) : GsonArrayElement() 14 | 15 | data class GsonObject(private val fieldMap: Map) : GsonArrayElement() { 16 | 17 | fun entries(): Set> { 18 | return fieldMap.entries 19 | } 20 | 21 | fun size(): Int { 22 | return fieldMap.size 23 | } 24 | } 25 | 26 | data class GsonArray( 27 | private val arrayFields: Map = HashMap(), 28 | val maxIndex: Int) : GsonModel() { 29 | 30 | fun entries(): Set> { 31 | return arrayFields.entries 32 | } 33 | 34 | operator fun get(arrayIndex: Int): GsonArrayElement? { 35 | return arrayFields[arrayIndex] 36 | } 37 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/TestUtils.kt: -------------------------------------------------------------------------------- 1 | package gsonpath 2 | 3 | import gsonpath.adapter.standard.model.GsonArray 4 | import gsonpath.adapter.standard.model.GsonArrayElement 5 | import gsonpath.adapter.standard.model.GsonModel 6 | import gsonpath.adapter.standard.model.GsonObject 7 | import org.hamcrest.Description 8 | import org.hamcrest.TypeSafeMatcher 9 | import javax.lang.model.element.Element 10 | 11 | infix fun A.toMap(that: B): Map = mapOf(Pair(this, that)) 12 | fun emptyGsonObject() = GsonObject(emptyMap()) 13 | fun simpleGsonObject(key: String, model: GsonModel) = GsonObject(key toMap model) 14 | fun simpleGsonArray(key: Int, model: GsonArrayElement) = GsonArray(key toMap model, key) 15 | 16 | fun processingExceptionMatcher(element: Element?, message: String): TypeSafeMatcher { 17 | return object : TypeSafeMatcher() { 18 | override fun describeTo(description: Description) { 19 | } 20 | 21 | override fun matchesSafely(item: ProcessingException): Boolean { 22 | return item.element == element && item.message == message 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/enums/EnumTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.enums 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class EnumTest { 8 | 9 | @Test 10 | fun testEnumWithoutDefault() { 11 | assertGeneratedContent(TestCriteria("generator/enums/without_default", 12 | absoluteSourceNames = listOf("generator/standard/TestGsonTypeFactory.java"), 13 | relativeSourceNames = listOf("TestEnumWithoutDefault.java"), 14 | relativeGeneratedNames = listOf("TestEnumWithoutDefault_GsonTypeAdapter.java") 15 | )) 16 | } 17 | 18 | @Test 19 | fun testEnumWithDefault() { 20 | assertGeneratedContent(TestCriteria("generator/enums/with_default", 21 | absoluteSourceNames = listOf("generator/standard/TestGsonTypeFactory.java"), 22 | relativeSourceNames = listOf("TestEnumWithDefault.java"), 23 | relativeGeneratedNames = listOf("TestEnumWithDefault_GsonTypeAdapter.java") 24 | )) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/model/FieldType.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.model 2 | 3 | import com.squareup.javapoet.TypeName 4 | import javax.lang.model.type.TypeMirror 5 | 6 | sealed class FieldType { 7 | abstract val typeName: TypeName 8 | abstract val elementTypeMirror: TypeMirror 9 | 10 | data class Primitive( 11 | override val typeName: TypeName, 12 | override val elementTypeMirror: TypeMirror) : FieldType() 13 | 14 | data class Other( 15 | override val typeName: TypeName, 16 | override val elementTypeMirror: TypeMirror) : FieldType() 17 | 18 | data class MapFieldType( 19 | override val typeName: TypeName, 20 | override val elementTypeMirror: TypeMirror) : FieldType() 21 | 22 | sealed class MultipleValues : FieldType() { 23 | 24 | data class Array( 25 | override val typeName: TypeName, 26 | override val elementTypeMirror: TypeMirror) : MultipleValues() 27 | 28 | data class Collection( 29 | override val typeName: TypeName, 30 | override val elementTypeMirror: TypeMirror) : MultipleValues() 31 | } 32 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/extension/SizeExtensionTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.extension 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class SizeExtensionTest { 8 | @Test 9 | fun testSizeMutable() { 10 | assertGeneratedContent(TestCriteria("generator/extension/size/valid/mutable", 11 | absoluteSourceNames = listOf("generator/standard/TestGsonTypeFactory.java"), 12 | relativeSourceNames = listOf("TestMutableSize.java"), 13 | relativeGeneratedNames = listOf("TestMutableSize_GsonTypeAdapter.java") 14 | )) 15 | } 16 | 17 | @Test 18 | fun testSizeImmutable() { 19 | assertGeneratedContent(TestCriteria("generator/extension/size/valid/immutable", 20 | absoluteSourceNames = listOf("generator/standard/TestGsonTypeFactory.java"), 21 | relativeSourceNames = listOf("TestImmutableSize.java"), 22 | relativeGeneratedNames = listOf("TestImmutableSize_GsonTypeAdapter.java") 23 | )) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'kotlin' 3 | apply plugin: 'kotlin-kapt' 4 | apply from: "${project.rootDir}/scripts/clean-util.gradle" 5 | 6 | targetCompatibility = JavaVersion.VERSION_1_8 7 | sourceCompatibility = JavaVersion.VERSION_1_8 8 | 9 | buildscript { 10 | repositories { 11 | maven { 12 | url "https://plugins.gradle.org/m2/" 13 | } 14 | mavenCentral() 15 | } 16 | dependencies { 17 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 18 | } 19 | } 20 | 21 | kapt { 22 | arguments { 23 | arg("gsonpath.incremental", "true") 24 | arg("gsonpath.additionalAnnotations", 25 | "gsonpath.SampleAdapterFactory," + 26 | "gsonpath.kotlin.CustomAnnotation," + 27 | "gsonpath.kotlin.TypeSubType") 28 | } 29 | } 30 | 31 | dependencies { 32 | compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 33 | compile "com.google.code.gson:gson:$gson_version" 34 | 35 | compile project(":sample-base") 36 | kapt project(":compiler:standard") 37 | 38 | testCompile "junit:junit:$junit_version" 39 | } -------------------------------------------------------------------------------- /sample/src/test/resources/GsonErrorTestJson.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleValue": { 3 | "values": [ 4 | { 5 | "text": "valid" 6 | }, 7 | { 8 | "text": null 9 | } 10 | ] 11 | }, 12 | "listValue": [ 13 | { 14 | "values": [ 15 | { 16 | "text": "valid" 17 | }, 18 | { 19 | "text": null 20 | } 21 | ] 22 | }, 23 | { 24 | "values": [ 25 | { 26 | "text": "valid" 27 | }, 28 | { 29 | "text": null 30 | } 31 | ] 32 | } 33 | ], 34 | "arrayValue": [ 35 | { 36 | "values": [ 37 | { 38 | "text": "valid" 39 | }, 40 | { 41 | "text": "" 42 | } 43 | ] 44 | }, 45 | { 46 | "values": [ 47 | { 48 | "text": "valid" 49 | }, 50 | { 51 | "text": "123456" 52 | } 53 | ] 54 | } 55 | ], 56 | "mapValue": { 57 | "key1" : { 58 | "values": [ 59 | { 60 | "text": "valid" 61 | }, 62 | { 63 | "text": null 64 | } 65 | ] 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/unit/model/FieldInfoTestFactory.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.unit.model 2 | 3 | import com.google.gson.annotations.SerializedName 4 | import com.nhaarman.mockitokotlin2.mock 5 | import com.squareup.javapoet.TypeName 6 | import gsonpath.model.FieldInfo 7 | import gsonpath.model.FieldType 8 | import org.mockito.Mockito 9 | import org.mockito.Mockito.`when` as whenever 10 | 11 | object FieldInfoTestFactory { 12 | fun mockFieldInfo(fieldName: String, jsonPath: String? = null): FieldInfo { 13 | val fieldInfo = Mockito.mock(FieldInfo::class.java) 14 | whenever(fieldInfo.fieldType).thenReturn(FieldType.Primitive(TypeName.INT, mock())) 15 | whenever(fieldInfo.annotationNames).thenReturn(emptyList()) 16 | whenever(fieldInfo.fieldName).thenReturn(fieldName) 17 | 18 | if (jsonPath != null) { 19 | val serializedName = Mockito.mock(SerializedName::class.java) 20 | whenever(serializedName.value).thenReturn(jsonPath) 21 | whenever(serializedName.alternate).thenReturn(emptyArray()) 22 | whenever(fieldInfo.getAnnotation(SerializedName::class.java)).thenReturn(serializedName) 23 | } 24 | 25 | return fieldInfo 26 | } 27 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/empty/ignored_fields/TestIgnoredFields_GsonTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package generator.standard.empty.ignored_fields; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonWriter; 6 | import gsonpath.annotation.GsonPathGenerated; 7 | import gsonpath.internal.GsonPathTypeAdapter; 8 | import gsonpath.internal.JsonReaderHelper; 9 | 10 | import java.io.IOException; 11 | import java.lang.Override; 12 | 13 | @GsonPathGenerated 14 | public final class TestIgnoredFields_GsonTypeAdapter extends GsonPathTypeAdapter { 15 | public TestIgnoredFields_GsonTypeAdapter(Gson gson) { 16 | super(gson); 17 | } 18 | 19 | @Override 20 | public TestIgnoredFields readImpl(JsonReader in) throws IOException { 21 | TestIgnoredFields result = new TestIgnoredFields(); 22 | JsonReaderHelper jsonReaderHelper = new JsonReaderHelper(in, 1, 0); 23 | 24 | return result; 25 | } 26 | 27 | @Override 28 | public void writeImpl(JsonWriter out, TestIgnoredFields value) throws IOException { 29 | // Begin 30 | out.beginObject(); 31 | // End 32 | out.endObject(); 33 | } 34 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/empty/invalid_fields/TestInvalidFields_GsonTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package generator.standard.empty.invalid_fields; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonWriter; 6 | import gsonpath.annotation.GsonPathGenerated; 7 | import gsonpath.internal.GsonPathTypeAdapter; 8 | import gsonpath.internal.JsonReaderHelper; 9 | 10 | import java.io.IOException; 11 | import java.lang.Override; 12 | 13 | @GsonPathGenerated 14 | public final class TestInvalidFields_GsonTypeAdapter extends GsonPathTypeAdapter { 15 | public TestInvalidFields_GsonTypeAdapter(Gson gson) { 16 | super(gson); 17 | } 18 | 19 | @Override 20 | public TestInvalidFields readImpl(JsonReader in) throws IOException { 21 | TestInvalidFields result = new TestInvalidFields(); 22 | JsonReaderHelper jsonReaderHelper = new JsonReaderHelper(in, 1, 0); 23 | 24 | return result; 25 | } 26 | 27 | @Override 28 | public void writeImpl(JsonWriter out, TestInvalidFields value) throws IOException { 29 | // Begin 30 | out.beginObject(); 31 | // End 32 | out.endObject(); 33 | } 34 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/internal/GsonPathTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package gsonpath.internal; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.stream.JsonReader; 6 | import com.google.gson.stream.JsonWriter; 7 | 8 | import java.io.IOException; 9 | 10 | import static gsonpath.internal.GsonUtil.isValidValue; 11 | 12 | public abstract class GsonPathTypeAdapter extends TypeAdapter { 13 | protected final Gson gson; 14 | 15 | public GsonPathTypeAdapter(Gson gson) { 16 | this.gson = gson; 17 | } 18 | 19 | @Override 20 | public final T read(JsonReader in) throws IOException { 21 | // Ensure the object is not null. 22 | if (!isValidValue(in)) { 23 | return null; 24 | } 25 | return readImpl(in); 26 | } 27 | 28 | @Override 29 | public final void write(JsonWriter out, T value) throws IOException { 30 | if (value == null) { 31 | out.nullValue(); 32 | return; 33 | } 34 | 35 | writeImpl(out, value); 36 | } 37 | 38 | public abstract T readImpl(JsonReader in) throws IOException; 39 | 40 | public abstract void writeImpl(JsonWriter out, T value) throws IOException; 41 | } 42 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/empty/annotation_only/TestAnnotationOnly_GsonTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package generator.standard.empty.annotation_only; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonWriter; 6 | import gsonpath.annotation.GsonPathGenerated; 7 | import gsonpath.internal.GsonPathTypeAdapter; 8 | import gsonpath.internal.JsonReaderHelper; 9 | 10 | import java.io.IOException; 11 | import java.lang.Override; 12 | 13 | @GsonPathGenerated 14 | public final class TestAnnotationOnly_GsonTypeAdapter extends GsonPathTypeAdapter { 15 | public TestAnnotationOnly_GsonTypeAdapter(Gson gson) { 16 | super(gson); 17 | } 18 | 19 | @Override 20 | public TestAnnotationOnly readImpl(JsonReader in) throws IOException { 21 | TestAnnotationOnly result = new TestAnnotationOnly(); 22 | JsonReaderHelper jsonReaderHelper = new JsonReaderHelper(in, 1, 0); 23 | 24 | return result; 25 | } 26 | 27 | @Override 28 | public void writeImpl(JsonWriter out, TestAnnotationOnly value) throws IOException { 29 | // Begin 30 | out.beginObject(); 31 | // End 32 | out.endObject(); 33 | } 34 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/use_getter_annotation/UseGetterAnnotationTest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.use_getter_annotation; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.GsonFieldValidationType; 5 | import gsonpath.annotation.AutoGsonAdapter; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | public abstract class UseGetterAnnotationTest { 9 | @SerializedName("common.") 10 | @NotNull 11 | public abstract String getName(); 12 | 13 | private UseGetterAnnotationTest() { 14 | } 15 | 16 | @AutoGsonAdapter(fieldValidationType = GsonFieldValidationType.VALIDATE_EXPLICIT_NON_NULL) 17 | public static final class Implementation extends UseGetterAnnotationTest { 18 | private final String name; 19 | @SerializedName("specific.") 20 | private int intTest = 5; 21 | 22 | @Override 23 | public String getName() { 24 | return this.name; 25 | } 26 | 27 | public final int getIntTest() { 28 | return this.intTest; 29 | } 30 | 31 | public Implementation(@NotNull String name, int intTest) { 32 | this.name = name; 33 | this.intTest = intTest; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sample/src/test/java/gsonpath/TestUtil.kt: -------------------------------------------------------------------------------- 1 | package gsonpath 2 | 3 | import com.google.gson.Gson 4 | import com.google.gson.GsonBuilder 5 | import com.google.gson.JsonParseException 6 | import org.junit.Assert 7 | import java.io.InputStreamReader 8 | 9 | object TestUtil { 10 | 11 | fun createGson(): Gson = GsonBuilder() 12 | .registerTypeAdapterFactory(GsonPathTypeAdapterFactory()) 13 | .registerTypeAdapterFactory(GsonPath.createTypeAdapterFactory(TestGsonTypeFactory::class.java)) 14 | .create() 15 | 16 | fun executeFromJson(clazz: Class, jsonString: String): T = createGson() 17 | .fromJson(jsonString, clazz) 18 | 19 | fun expectException(clazz: Class<*>, jsonString: String, message: String) { 20 | val exception: JsonParseException? = 21 | try { 22 | executeFromJson(clazz, jsonString) 23 | null 24 | 25 | } catch (e: JsonParseException) { 26 | e 27 | } 28 | 29 | if (exception != null) { 30 | Assert.assertEquals(message, exception.message) 31 | return 32 | } 33 | 34 | Assert.fail("Expected exception was not thrown.") 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /compiler/standard/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: "kotlin" 3 | apply from: "${project.rootDir}/scripts/jacoco-setup.gradle" 4 | apply from: "${project.rootDir}/scripts/clean-util.gradle" 5 | 6 | buildscript { 7 | repositories { 8 | mavenCentral() 9 | } 10 | dependencies { 11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 | classpath 'com.vanniktech:gradle-maven-publish-plugin:0.7.0' 13 | } 14 | } 15 | 16 | apply plugin: "com.vanniktech.maven.publish" 17 | 18 | targetCompatibility = JavaVersion.VERSION_1_8 19 | sourceCompatibility = JavaVersion.VERSION_1_8 20 | 21 | dependencies { 22 | compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 23 | 24 | compile project(":library") 25 | compile project(":compiler:base") 26 | 27 | compile "com.squareup:javapoet:$javapoet_version" 28 | compile "com.google.auto:auto-common:0.6" 29 | compile "com.google.code.gson:gson:$gson_version" 30 | 31 | testCompile "com.nhaarman.mockitokotlin2:mockito-kotlin:2.0.0" 32 | testCompile "com.google.truth:truth:0.34" 33 | testCompile "com.google.testing.compile:compile-testing:0.18" 34 | testCompile files(org.gradle.internal.jvm.Jvm.current().getToolsJar()) 35 | } 36 | -------------------------------------------------------------------------------- /library/src/test/java/gsonpath/safe/GsonSafeListTest.java: -------------------------------------------------------------------------------- 1 | package gsonpath.safe; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.reflect.TypeToken; 6 | import gsonpath.GsonPathTypeAdapterFactory; 7 | import gsonpath.GsonSafeList; 8 | import org.junit.Test; 9 | 10 | import java.io.InputStream; 11 | import java.io.InputStreamReader; 12 | 13 | import static org.junit.Assert.assertEquals; 14 | 15 | public class GsonSafeListTest { 16 | @Test 17 | public void testUsingGsonSafeArrayList() { 18 | Gson gson = new GsonBuilder() 19 | .registerTypeAdapterFactory(new GsonPathTypeAdapterFactory()) 20 | .create(); 21 | 22 | InputStream resourceAsStream = ClassLoader 23 | .getSystemClassLoader() 24 | .getResourceAsStream("sample.json"); 25 | 26 | GsonSafeList typesList = gson.fromJson( 27 | new InputStreamReader(resourceAsStream), 28 | new TypeToken>() { 29 | }.getType()); 30 | 31 | assertEquals(2, typesList.size()); 32 | assertEquals(new Integer(1), typesList.get(0)); 33 | assertEquals(new Integer(4), typesList.get(1)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/extension/RemoveInvalidElementsTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.extension 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class RemoveInvalidElementsTest { 8 | @Test 9 | fun testRemoveInvalidElementsMutable() { 10 | assertGeneratedContent(TestCriteria("generator/extension/invalid/mutable", 11 | absoluteSourceNames = listOf("generator/standard/TestGsonTypeFactory.java"), 12 | relativeSourceNames = listOf("TestMutableRemoveInvalidElements.java"), 13 | relativeGeneratedNames = listOf("TestMutableRemoveInvalidElements_GsonTypeAdapter.java") 14 | )) 15 | } 16 | 17 | @Test 18 | fun testRemoveInvalidElementsImmutable() { 19 | assertGeneratedContent(TestCriteria("generator/extension/invalid/immutable", 20 | absoluteSourceNames = listOf("generator/standard/TestGsonTypeFactory.java"), 21 | relativeSourceNames = listOf("TestImmutableRemoveInvalidElements.java"), 22 | relativeGeneratedNames = listOf("TestImmutableRemoveInvalidElements_GsonTypeAdapter.java") 23 | )) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/factory/TestGsonTypeFactoryImpl.java: -------------------------------------------------------------------------------- 1 | package generator.factory; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.TypeAdapterFactory; 6 | import com.google.gson.reflect.TypeToken; 7 | 8 | import java.lang.Override; 9 | 10 | public final class TestGsonTypeFactoryImpl implements TestGsonTypeFactory { 11 | private final TypeAdapterFactory[] mPackagePrivateLoaders; 12 | 13 | public GsonTypeAdapterLoader() { 14 | mPackagePrivateLoaders = new TypeAdapterFactory[3]; 15 | mPackagePrivateLoaders[0] = new generator.factory.PackagePrivateTypeAdapterLoader(); 16 | mPackagePrivateLoaders[1] = new generator.factory.source2.PackagePrivateTypeAdapterLoader(); 17 | mPackagePrivateLoaders[2] = new generator.factory.source3.PackagePrivateTypeAdapterLoader(); 18 | } 19 | 20 | @Override 21 | public TypeAdapter create(Gson gson, TypeToken type) { 22 | for (int i = 0; i < mPackagePrivateLoaders.length; i++) { 23 | TypeAdapter typeAdapter = mPackagePrivateLoaders[i].create(gson, type); 24 | 25 | if (typeAdapter != null) { 26 | return typeAdapter; 27 | } 28 | } 29 | return null; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/enums/EnumAdapterFactory.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.enums 2 | 3 | import gsonpath.LazyFactoryMetadata 4 | import gsonpath.adapter.AdapterFactory 5 | import gsonpath.adapter.AdapterGenerationResult 6 | import gsonpath.adapter.util.AdapterFactoryUtil.getAnnotatedModelElements 7 | import gsonpath.annotation.EnumGsonAdapter 8 | import gsonpath.dependencies.Dependencies 9 | import gsonpath.util.Logger 10 | import javax.annotation.processing.RoundEnvironment 11 | import javax.lang.model.element.ElementKind 12 | import javax.lang.model.element.TypeElement 13 | 14 | object EnumAdapterFactory : AdapterFactory { 15 | 16 | override fun generateGsonAdapters( 17 | env: RoundEnvironment, 18 | logger: Logger, 19 | lazyFactoryMetadata: LazyFactoryMetadata, 20 | annotations: Set, 21 | dependencies: Dependencies): List { 22 | 23 | return getAnnotatedModelElements(env, annotations, listOf(ElementKind.ENUM)) 24 | .onEach { logger.printMessage("Generating TypeAdapter (${it.element})") } 25 | .map { 26 | dependencies.enumGsonAdapterGenerator.handle(it.element, it.annotation, lazyFactoryMetadata) 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/adapter/subType/Type.java: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.subType; 2 | 3 | import gsonpath.Nullable; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | import gsonpath.annotation.GsonSubtype; 6 | import gsonpath.annotation.GsonSubtypeGetter; 7 | 8 | @GsonSubtype( 9 | jsonKeys = {"type"} 10 | ) 11 | public abstract class Type { 12 | 13 | @GsonSubtypeGetter 14 | static Class getSubType(@Nullable String type) { 15 | if (type == null) { 16 | return TypeNull.class; 17 | } 18 | switch (type) { 19 | case "type1": 20 | return Type1.class; 21 | case "type2": 22 | return Type2.class; 23 | case "type3": 24 | return Type3.class; 25 | } 26 | return null; 27 | } 28 | 29 | String type; 30 | String name; 31 | 32 | @AutoGsonAdapter 33 | public static class Type1 extends Type { 34 | int intTest; 35 | } 36 | 37 | @AutoGsonAdapter 38 | public static class Type2 extends Type { 39 | double doubleTest; 40 | } 41 | 42 | @AutoGsonAdapter 43 | public static class Type3 extends Type { 44 | String stringTest; 45 | } 46 | 47 | @AutoGsonAdapter 48 | public static class TypeNull extends Type { 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/StandardAdapterFactory.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard 2 | 3 | import gsonpath.LazyFactoryMetadata 4 | import gsonpath.adapter.AdapterFactory 5 | import gsonpath.adapter.AdapterGenerationResult 6 | import gsonpath.adapter.util.AdapterFactoryUtil.getAnnotatedModelElements 7 | import gsonpath.annotation.AutoGsonAdapter 8 | import gsonpath.dependencies.Dependencies 9 | import gsonpath.util.Logger 10 | import javax.annotation.processing.RoundEnvironment 11 | import javax.lang.model.element.ElementKind 12 | import javax.lang.model.element.TypeElement 13 | 14 | object StandardAdapterFactory : AdapterFactory { 15 | 16 | override fun generateGsonAdapters( 17 | env: RoundEnvironment, 18 | logger: Logger, 19 | lazyFactoryMetadata: LazyFactoryMetadata, 20 | annotations: Set, 21 | dependencies: Dependencies): List { 22 | 23 | return getAnnotatedModelElements(env, annotations, listOf(ElementKind.CLASS, ElementKind.INTERFACE)) 24 | .onEach { logger.printMessage("Generating TypeAdapter (${it.element})") } 25 | .map { 26 | dependencies.standardGsonAdapterGenerator.handle(it.element, it.annotation, lazyFactoryMetadata) 27 | } 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/internal/GsonUtil.java: -------------------------------------------------------------------------------- 1 | package gsonpath.internal; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.stream.JsonReader; 6 | import com.google.gson.stream.JsonToken; 7 | import com.google.gson.stream.JsonWriter; 8 | 9 | import java.io.IOException; 10 | 11 | /** 12 | * A set of Gson utilities which expose functionality to read content from a JsonReader 13 | * safely without throwing IOExceptions. 14 | */ 15 | public class GsonUtil { 16 | 17 | private GsonUtil() { 18 | } 19 | 20 | /** 21 | * Determines whether the next value within the reader is not null. 22 | * 23 | * @param in the json reader used to read the stream 24 | * @return true if a valid value exists, or false if the value is null. 25 | * @throws IOException see {@link JsonReader#skipValue()} 26 | */ 27 | public static boolean isValidValue(JsonReader in) throws IOException { 28 | if (in.peek() == JsonToken.NULL) { 29 | in.skipValue(); 30 | return false; 31 | } 32 | return true; 33 | } 34 | 35 | public static void writeWithGenericAdapter(Gson gson, Class clazz, JsonWriter out, T obj0) throws IOException { 36 | TypeAdapter adapter = gson.getAdapter(clazz); 37 | adapter.write(out, obj0); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sample/src/test/java/gsonpath/mandatory/MandatoryFieldTest.java: -------------------------------------------------------------------------------- 1 | package gsonpath.mandatory; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.JsonParseException; 6 | import gsonpath.GsonPath; 7 | import gsonpath.TestGsonTypeFactory; 8 | import gsonpath.exception.JsonFieldNoKeyException; 9 | import org.junit.Assert; 10 | import org.junit.Test; 11 | 12 | import java.io.InputStream; 13 | import java.io.InputStreamReader; 14 | 15 | public class MandatoryFieldTest { 16 | @Test 17 | public void test() { 18 | GsonBuilder builder = new GsonBuilder(); 19 | builder.registerTypeAdapterFactory(GsonPath.createTypeAdapterFactory(TestGsonTypeFactory.class)); 20 | 21 | ClassLoader classLoader = ClassLoader.getSystemClassLoader(); 22 | InputStream resourceAsStream = classLoader.getResourceAsStream("MandatoryTestJson.json"); 23 | 24 | Gson gson = builder.create(); 25 | 26 | try { 27 | gson.fromJson(new InputStreamReader(resourceAsStream), MandatorySampleModel.class); 28 | 29 | } catch (JsonParseException e) { 30 | // Since the mandatory value is not found, we are expecting an exception. 31 | Assert.assertEquals(e.getClass(), JsonFieldNoKeyException.class); 32 | return; 33 | } 34 | 35 | Assert.fail("Expected JsonFieldMissingException was not triggered"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/interface_test/InterfaceExample.java: -------------------------------------------------------------------------------- 1 | package gsonpath.interface_test; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | @AutoGsonAdapter 6 | interface InterfaceExample { 7 | Integer getIntExample(); 8 | 9 | Long getLongExample(); 10 | 11 | Double getDoubleExample(); 12 | 13 | Boolean getBooleanExample(); 14 | 15 | Integer[] getIntArrayExample(); 16 | 17 | Long[] getLongArrayExample(); 18 | 19 | Double[] getDoubleArrayExample(); 20 | 21 | Boolean[] getBooleanArrayExample(); 22 | 23 | static InterfaceExample create(Integer intExample, 24 | Long longExample, 25 | Double doubleExample, 26 | Boolean booleanExample, 27 | Integer[] intArrayExample, 28 | Long[] longArrayExample, 29 | Double[] doubleArrayExample, 30 | Boolean[] booleanArrayExample) { 31 | 32 | return new InterfaceExample_GsonPathModel( 33 | intExample, 34 | longExample, 35 | doubleExample, 36 | booleanExample, 37 | intArrayExample, 38 | longArrayExample, 39 | doubleArrayExample, 40 | booleanArrayExample 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/annotation/PathSubstitution.java: -------------------------------------------------------------------------------- 1 | package gsonpath.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | /** 7 | * Provides a text substitution mechanism to the com.google.gson.annotations.SerializedName annotation 8 | * when used in conjunction with the {@link AutoGsonAdapter}. 9 | *

10 | * A string replacement is performed by looking for the original text wrapped wih curly braces (e.g. for a original 11 | * term of 'ORIGINAL', the string replacement actually looks for '{ORIGINAL}', and replaces it with the replacement 12 | * text. This is very useful for when used with inheritance, as you can define a base class with substitution values, 13 | * and then specify a different replacement values within each concrete class. 14 | * 15 | * @author Lachlan McKee 16 | */ 17 | @Retention(RetentionPolicy.RUNTIME) 18 | public @interface PathSubstitution { 19 | /** 20 | * The original text which will be replaced 21 | *

22 | * The text replacement looks for the text with surrounding curly braces. 23 | * e.g. for a original term of 'ORIGINAL', the string replacement actually looks for '{ORIGINAL}' 24 | * 25 | * @return the original text 26 | */ 27 | String original(); 28 | 29 | /** 30 | * The text used to override the original text. 31 | * 32 | * @return the replacement text 33 | */ 34 | String replacement(); 35 | } 36 | -------------------------------------------------------------------------------- /sample/src/main/java/gsonpath/adapter/standard/extension/range/floatrange/FloatRangeModel.java: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.extension.range.floatrange; 2 | 3 | import gsonpath.annotation.AutoGsonAdapter; 4 | 5 | public interface FloatRangeModel { 6 | 7 | interface BaseModel { 8 | T getValue(); 9 | } 10 | 11 | interface BaseFloatModel extends BaseModel { 12 | } 13 | 14 | interface BaseDoubleModel extends BaseModel { 15 | } 16 | 17 | interface Inclusive { 18 | @AutoGsonAdapter 19 | interface FloatModel extends BaseFloatModel { 20 | @android.support.annotation.FloatRange(from = 0, to = 5) 21 | Float getValue(); 22 | } 23 | 24 | @AutoGsonAdapter 25 | interface DoubleModel extends BaseDoubleModel { 26 | @gsonpath.extension.annotation.FloatRange(from = 0, to = 5) 27 | Double getValue(); 28 | } 29 | } 30 | 31 | interface Exclusive { 32 | @AutoGsonAdapter 33 | interface FloatModel extends BaseFloatModel { 34 | @android.support.annotation.FloatRange(from = 0, to = 5, fromInclusive = false, toInclusive = false) 35 | Float getValue(); 36 | } 37 | 38 | @AutoGsonAdapter 39 | interface DoubleModel extends BaseDoubleModel { 40 | @gsonpath.extension.annotation.FloatRange(from = 0, to = 5, fromInclusive = false, toInclusive = false) 41 | Double getValue(); 42 | } 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/interf/java8/TestJava8Interface_GsonPathModel.java: -------------------------------------------------------------------------------- 1 | package generator.interf.java8; 2 | 3 | import gsonpath.annotation.GsonPathGenerated; 4 | import java.lang.Integer; 5 | import java.lang.Object; 6 | import java.lang.Override; 7 | import java.lang.String; 8 | 9 | @GsonPathGenerated 10 | public final class TestJava8Interface_GsonPathModel implements TestJava8Interface { 11 | private final Integer value1; 12 | 13 | public TestJava8Interface_GsonPathModel(Integer value1) { 14 | this.value1 = value1; 15 | } 16 | 17 | @Override 18 | public Integer getValue1() { 19 | return value1; 20 | } 21 | 22 | @Override 23 | public boolean equals(Object o) { 24 | if (this == o) { 25 | return true; 26 | } 27 | if (o == null || getClass() != o.getClass()) { 28 | return false; 29 | } 30 | 31 | TestJava8Interface_GsonPathModel equalsOtherType = (TestJava8Interface_GsonPathModel) o; 32 | 33 | if (value1 != null ? !value1.equals(equalsOtherType.value1) : equalsOtherType.value1 != null) { 34 | return false; 35 | } 36 | 37 | return true; 38 | } 39 | 40 | @Override 41 | public int hashCode() { 42 | int hashCodeReturnValue = value1 != null ? value1.hashCode() : 0; 43 | return hashCodeReturnValue; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "TestJava8Interface{" + 49 | "value1=" + value1 + 50 | '}'; 51 | } 52 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/model/MandatoryFieldInfoFactory.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.model 2 | 3 | class MandatoryFieldInfoFactory { 4 | 5 | /** 6 | * Add any mandatory field indexes as constants. This is done for code readability. 7 | * We will obtain the values using a depth-first recursion. 8 | */ 9 | fun createMandatoryFieldsFromGsonObject(gsonObject: GsonObject): List { 10 | return gsonObject.entries() 11 | .flatMap { (_, gsonModel) -> 12 | when (gsonModel) { 13 | is GsonField -> handleField(gsonModel) 14 | is GsonObject -> createMandatoryFieldsFromGsonObject(gsonModel) 15 | is GsonArray -> { 16 | gsonModel.entries() 17 | .flatMap { (_, arrayGsonModel) -> 18 | when (arrayGsonModel) { 19 | is GsonField -> handleField(arrayGsonModel) 20 | is GsonObject -> createMandatoryFieldsFromGsonObject(arrayGsonModel) 21 | } 22 | } 23 | } 24 | } 25 | } 26 | } 27 | 28 | private fun handleField(gsonField: GsonField): List { 29 | return when { 30 | gsonField.isRequired -> listOf(gsonField) 31 | else -> emptyList() 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/model/SerializedNameFetcher.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.model 2 | 3 | import com.google.gson.annotations.SerializedName 4 | import gsonpath.ProcessingException 5 | import gsonpath.annotation.NestedJson 6 | import gsonpath.model.FieldInfo 7 | 8 | object SerializedNameFetcher { 9 | fun getSerializedName(fieldInfo: FieldInfo, flattenDelimiter: Char): String? { 10 | val serializedNameAnnotation = fieldInfo.getAnnotation(SerializedName::class.java) 11 | val nestedJson = fieldInfo.getAnnotation(NestedJson::class.java) 12 | 13 | // SerializedName 'alternate' is not supported and should fail fast. 14 | serializedNameAnnotation?.let { 15 | if (it.alternate.isNotEmpty()) { 16 | throw ProcessingException("SerializedName 'alternate' feature is not supported", fieldInfo.element) 17 | } 18 | } 19 | 20 | nestedJson?.let { 21 | if (it.value.endsWith(flattenDelimiter)) { 22 | throw ProcessingException("NestedJson path must not end with '$flattenDelimiter'", fieldInfo.element) 23 | } 24 | } 25 | 26 | return when { 27 | nestedJson != null && serializedNameAnnotation != null -> { 28 | nestedJson.value + flattenDelimiter + serializedNameAnnotation.value 29 | } 30 | nestedJson != null -> nestedJson.value + flattenDelimiter 31 | serializedNameAnnotation != null -> serializedNameAnnotation.value 32 | else -> null 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/util/SunTreesProvider.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.util 2 | 3 | import com.sun.source.util.Trees 4 | import javax.annotation.processing.ProcessingEnvironment 5 | 6 | /** 7 | * Typically the 'com.sun.source.util.Trees' class is not allowed when making an annotation processor incremental. 8 | * A work around (found here: https://github.com/JakeWharton/butterknife/commit/3f675f4e23e59f645f5cecddde9f3b9fb1925cf8#diff-141a2db288c994f07eba0c49a2869e9bR155) 9 | * was implemented to still allow Trees to be used. 10 | */ 11 | class SunTreesProvider(private val env: ProcessingEnvironment) { 12 | private val lazyTrees: Trees by lazy { 13 | try { 14 | Trees.instance(env) 15 | } catch (ignored: IllegalArgumentException) { 16 | try { 17 | // Get original ProcessingEnvironment from Gradle-wrapped one or KAPT-wrapped one. 18 | env.javaClass.declaredFields 19 | .first { field -> 20 | field.name == "delegate" || field.name == "processingEnv" 21 | } 22 | .let { field -> 23 | field.isAccessible = true 24 | val javacEnv = field.get(env) as ProcessingEnvironment 25 | Trees.instance(javacEnv) 26 | } 27 | } catch (throwable: Throwable) { 28 | throw IllegalStateException("Unable to create Trees", throwable) 29 | } 30 | } 31 | } 32 | 33 | fun getTrees(): Trees = lazyTrees 34 | } -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/model/FieldInfo.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.model 2 | 3 | import javax.lang.model.element.Element 4 | 5 | /** 6 | * Contains important information about a class field within a class annotated with the AutoGsonAdapter annotation. 7 | */ 8 | interface FieldInfo { 9 | val fieldType: FieldType 10 | 11 | /** 12 | * The name of the class that field is contained within. 13 | */ 14 | val parentClassName: String 15 | 16 | /** 17 | * Searches for an annotation that is attached to the field. 18 | */ 19 | fun getAnnotation(annotationClass: Class): T? 20 | 21 | /** 22 | * The name of the field this [FieldInfo] represents. 23 | */ 24 | val fieldName: String 25 | 26 | /** 27 | * The mechanism for accessing the field from the class. 28 | * 29 | * This allows the library to either access the variable via an exposed field, or potentially a getter instead. 30 | */ 31 | val fieldAccessor: String 32 | 33 | /** 34 | * Returns the raw names of all annotations attached to the field. 35 | * 36 | * This is useful for finding annotations without having the annotation class included in the 37 | * annotation processor library. 38 | */ 39 | val annotationNames: List 40 | 41 | /** 42 | * The raw annotation processor field element. 43 | * This should mainly be used for reporting errors back to the user. 44 | */ 45 | val element: Element 46 | 47 | /** 48 | * Whether the field has a default value assigned. 49 | */ 50 | val hasDefaultValue: Boolean 51 | } 52 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/util/FieldNamingPolicyMapper.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.util 2 | 3 | import com.google.gson.FieldNamingPolicy 4 | import gsonpath.ProcessingException 5 | import java.lang.reflect.Field 6 | 7 | class FieldNamingPolicyMapper { 8 | 9 | /** 10 | * Applies the gson field naming policy using the given field name. 11 | 12 | * @param fieldNamingPolicy the field naming policy to apply 13 | * * 14 | * @param fieldName the name being altered. 15 | * * 16 | * @return the altered name. 17 | */ 18 | @Throws(ProcessingException::class) 19 | fun applyFieldNamingPolicy(fieldNamingPolicy: FieldNamingPolicy, fieldName: String): String { 20 | // 21 | // Unfortunately the field naming policy uses a Field parameter to translate name. 22 | // As a result, for now it was decided to create a fake field class which supplies the correct name, 23 | // as opposed to copying the logic from GSON and potentially breaking compatibility if they add another enum. 24 | // 25 | val fieldConstructor = Field::class.java.declaredConstructors[0] 26 | fieldConstructor.isAccessible = true 27 | val fakeField: Field 28 | try { 29 | fakeField = fieldConstructor.newInstance(null, fieldName, null, -1, -1, null, null) as Field 30 | 31 | } catch (e: Exception) { 32 | throw ProcessingException("Error while creating 'fake' field for naming policy.") 33 | } 34 | 35 | // Applies the naming transformation on the input field name. 36 | return fieldNamingPolicy.translateName(fakeField) 37 | } 38 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/using_constructor/valid/ValidConstructorTest.java: -------------------------------------------------------------------------------- 1 | package generator.standard.using_constructor.valid; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | import kotlin.jvm.internal.Intrinsics; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | /** 10 | * TODO: Once I figure out how to run the annotation processor tests on actual data classes, this file should be 11 | * changed to be an actual data class, rather than the Java code generated by the data class. 12 | * 13 | * If Jetbrains changes the way in which data clases are generated, this test will incorrectly still pass. 14 | */ 15 | @AutoGsonAdapter 16 | public final class ValidConstructorTest { 17 | @SerializedName("parent.child.") 18 | @NotNull 19 | private final String value1; 20 | private final boolean isBooleanTest1; 21 | @Nullable 22 | private final Boolean isBooleanTest2; 23 | 24 | @NotNull 25 | public final String getValue1() { 26 | return this.value1; 27 | } 28 | 29 | public final boolean isBooleanTest1() { 30 | return this.isBooleanTest1; 31 | } 32 | 33 | @Nullable 34 | public final Boolean isBooleanTest2() { 35 | return this.isBooleanTest2; 36 | } 37 | 38 | public ValidConstructorTest(@NotNull String value1, boolean isBooleanTest1, @Nullable Boolean isBooleanTest2) { 39 | Intrinsics.checkParameterIsNotNull(value1, "value1"); 40 | this.value1 = value1; 41 | this.isBooleanTest1 = isBooleanTest1; 42 | this.isBooleanTest2 = isBooleanTest2; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /sample/src/test/java/gsonpath/adapter/enums/EnumExampleTests.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.enums 2 | 3 | import gsonpath.TestUtil.createGson 4 | import gsonpath.audit.AuditJsonReader 5 | import org.junit.Assert.assertEquals 6 | import org.junit.Test 7 | import java.io.StringReader 8 | 9 | class EnumExampleTests { 10 | 11 | @Test 12 | fun testEnum() { 13 | val gsonPathJsonReader = AuditJsonReader(StringReader(""" 14 | { 15 | "values": [ 16 | "value1", 17 | "value-2", 18 | "value-3-and-4" 19 | ], 20 | "valuesWithDefault": ["UNEXPECTED"] 21 | } 22 | """.trimIndent())) 23 | 24 | val result = createGson() 25 | .getAdapter(EnumExample::class.java) 26 | .read(gsonPathJsonReader) 27 | 28 | assertEquals(3, result.values.size) 29 | assertEquals(EnumExample.EnumValue.VALUE1, result.values[0]) 30 | assertEquals(EnumExample.EnumValue.VALUE_2, result.values[1]) 31 | assertEquals(EnumExample.EnumValue.VALUE_3_AND_4, result.values[2]) 32 | 33 | assertEquals(1, result.valuesWithDefault.size) 34 | assertEquals(EnumExample.EnumValueWithDefault.VALUE1, result.valuesWithDefault[0]) 35 | 36 | val unexpectedEnumValues = gsonPathJsonReader.auditLog.unexpectedEnumValues 37 | assertEquals(1, unexpectedEnumValues.size) 38 | assertEquals("\$.valuesWithDefault[1]", unexpectedEnumValues[0].path) 39 | assertEquals("gsonpath.adapter.enums.EnumExample.EnumValueWithDefault", unexpectedEnumValues[0].typeName) 40 | assertEquals("UNEXPECTED", unexpectedEnumValues[0].value) 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/util/DefaultValueDetector.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.util 2 | 3 | import com.squareup.javapoet.ClassName 4 | import com.squareup.javapoet.TypeName 5 | import com.sun.source.tree.VariableTree 6 | import com.sun.source.util.TreePathScanner 7 | import javax.lang.model.element.Element 8 | 9 | interface DefaultValueDetector { 10 | fun hasDefaultValue(element: Element): Boolean 11 | } 12 | 13 | class DefaultValueDetectorImpl(private val sunTreesProvider: SunTreesProvider) : DefaultValueDetector { 14 | override fun hasDefaultValue(element: Element): Boolean { 15 | return DefaultValueScanner(element) 16 | .scan(sunTreesProvider.getTrees().getPath(element), null) != null 17 | } 18 | 19 | /** 20 | * Scans a field and detects whether a default value has been set. 21 | * 22 | * If a value has been set, the result will be an empty list, otherwise it will be null. 23 | */ 24 | private class DefaultValueScanner(val fieldElement: Element) : TreePathScanner?, Void>() { 25 | override fun visitVariable(node: VariableTree?, p: Void?): List? { 26 | // Ignore default values for Kotlin classes (the stubs always set a default, but the real bytecode does not) 27 | if (isKotlinClass(fieldElement.enclosingElement)) { 28 | return null 29 | } 30 | return node?.initializer?.let { emptyList() } 31 | } 32 | 33 | private fun isKotlinClass(element: Element): Boolean { 34 | return element.annotationMirrors.any { 35 | TypeName.get(it.annotationType.asElement().asType()) == ClassName.get("kotlin", "Metadata") 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/factory/TypeAdapterFactoryHandlersFactory.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.factory 2 | 3 | import com.google.gson.TypeAdapterFactory 4 | import com.squareup.javapoet.TypeName 5 | import gsonpath.ProcessingException 6 | import gsonpath.adapter.AdapterGenerationResult 7 | import javax.lang.model.element.TypeElement 8 | 9 | object TypeAdapterFactoryHandlersFactory { 10 | private val typeAdapterFactoryTypeName = TypeName.get(TypeAdapterFactory::class.java) 11 | 12 | fun createResults( 13 | factoryElement: TypeElement, 14 | generatedGsonAdapters: List): Map> { 15 | 16 | if (generatedGsonAdapters.isEmpty()) { 17 | return emptyMap() 18 | } 19 | 20 | // Ensure that the factory element only extends TypeAdapterFactory 21 | val factoryInterfaces = factoryElement.interfaces 22 | if (factoryInterfaces.size != 1 || TypeName.get(factoryInterfaces[0]) != typeAdapterFactoryTypeName) { 23 | throw ProcessingException("Interfaces annotated with @AutoGsonAdapterFactory must extend " + 24 | "com.google.gson.TypeAdapterFactory and no other interfaces.", factoryElement) 25 | } 26 | 27 | return generatedGsonAdapters.fold(emptyMap()) { map, generatedGsonAdapter -> 28 | val packageName = generatedGsonAdapter.adapterClassName.packageName() 29 | 30 | val newList: List = 31 | map[packageName]?.plus(generatedGsonAdapter) ?: listOf(generatedGsonAdapter) 32 | 33 | return@fold map.plus(Pair(packageName, newList)) 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /guides/path_substitution.md: -------------------------------------------------------------------------------- 1 | Path Substitution 2 | = 3 | Gson Path provides a mechanism to use basic json path support when using the `@SerializedName` annotation. The aim of the path substitution is to provide flexibility to developers to replace certain placeholders within the path. 4 | 5 | Example 6 | - 7 | This may be useful in situations where an API returns nearly identical json, however the keys may differ. The aim of this feature is to reuse as much code as possible, and avoid creating two completely different models, or using inheritance in conjunction with abstract methods. 8 | 9 | For example, given the following two similar json responses: 10 | 11 | ```json 12 | { 13 | "staff": { 14 | "name": "John Smith", 15 | "age": 50 16 | }, 17 | "address": "123 Fake St" 18 | } 19 | ``` 20 | ```json 21 | { 22 | "customer": { 23 | "name": "Jack Torrance", 24 | "age": 29 25 | }, 26 | "address": "Overlook Hotel" 27 | } 28 | ``` 29 | 30 | The following base model can be created: 31 | 32 | ```java 33 | public class ContactDetailsBase { 34 | @SerializedName("{PERSON_DETAILS_SUB}.") 35 | public String name; 36 | 37 | @SerializedName("{PERSON_DETAILS_SUB}.") 38 | public int age; 39 | 40 | public String address; 41 | } 42 | ``` 43 | 44 | And the two implementing classes would be as follows: 45 | 46 | ```java 47 | @AutoGsonAdapter(substitutions = { 48 | @PathSubstitution(original = "PERSON_DETAILS_SUB", replacement = "staff") 49 | }) 50 | public class StaffContactDetails extends ContactDetailsBase { 51 | } 52 | ``` 53 | ```java 54 | @AutoGsonAdapter(substitutions = { 55 | @PathSubstitution(original = "PERSON_DETAILS_SUB", replacement = "customer") 56 | }) 57 | public class CustomerContactDetails extends ContactDetailsBase { 58 | } 59 | ``` -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/extension/range/RangeFunctions.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.extension.range 2 | 3 | import com.squareup.javapoet.CodeBlock 4 | import gsonpath.adapter.standard.extension.addException 5 | import gsonpath.util.`if` 6 | 7 | /** 8 | * Creates the 'range' code validation code block. 9 | * 10 | * @param value the value being inspected 11 | * @param isFrom whether this is a 'from' or a 'to' range inspection 12 | * @param isInclusive whether the range validation is inclusive of the value 13 | * @param jsonPath the json path of the field being validated 14 | * @param variableName the name of the variable that is assigned back to the fieldName 15 | */ 16 | fun CodeBlock.Builder.handleRangeValue(value: String, 17 | isFrom: Boolean, 18 | isInclusive: Boolean, 19 | jsonPath: String, 20 | variableName: String): CodeBlock.Builder { 21 | 22 | val comparisonOperator: String = 23 | if (isFrom) { 24 | if (isInclusive) "<" else "<=" 25 | } else { 26 | if (isInclusive) ">" else ">=" 27 | } 28 | 29 | val expectedOperator: String = 30 | if (isFrom) { 31 | if (isInclusive) ">=" else ">" 32 | } else { 33 | if (isInclusive) "<=" else "<" 34 | } 35 | 36 | val label: String = if (isFrom) "from" else "to" 37 | 38 | return `if`("$variableName $comparisonOperator $value") { 39 | addException("Invalid '$label' range for JSON element '$jsonPath'. Expected: '$expectedOperator $value', " + 40 | """Found '" + $variableName + "'""") 41 | } 42 | } -------------------------------------------------------------------------------- /compiler/base/src/main/java/gsonpath/util/FieldGetterFinder.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.util 2 | 3 | import java.util.* 4 | import javax.lang.model.element.Element 5 | import javax.lang.model.element.ElementKind 6 | import javax.lang.model.element.TypeElement 7 | import javax.lang.model.type.ExecutableType 8 | 9 | class FieldGetterFinder(private val typeHandler: TypeHandler) { 10 | /** 11 | * Attempts to find a logical getter method for a variable. 12 | * 13 | * For example, the following getter method names are valid for a variable named 'foo': 14 | * 'foo()', 'isFoo()', 'hasFoo()', 'getFoo()' 15 | * 16 | * If no getter method is found, an exception will be fired. 17 | * 18 | * @param parentElement the parent element of the field. 19 | * @param variableElement the field element we want to find the getter method for. 20 | */ 21 | fun findGetter(parentElement: TypeElement, variableElement: Element): Element? { 22 | return typeHandler.getAllMembers(parentElement) 23 | .asSequence() 24 | .filter { it.kind == ElementKind.METHOD } 25 | .filter { isMethodNameGetter(it, variableElement) } 26 | .find { (it.asType() as ExecutableType).parameterTypes.size == 0 } 27 | } 28 | 29 | /** 30 | * Determines if the method name either matches the variable name, or starts with a standard getter prefix. 31 | */ 32 | private fun isMethodNameGetter(methodElement: Element, variableElement: Element): Boolean { 33 | val remainder = methodElement.simpleName.toString() 34 | .toLowerCase(Locale.ENGLISH) 35 | .replace(variableElement.simpleName.toString().toLowerCase(Locale.ENGLISH), "") 36 | return arrayOf("", "is", "has", "get").contains(remainder) 37 | } 38 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/enums/EnumFieldLabelMapper.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.enums 2 | 3 | import com.google.gson.FieldNamingPolicy 4 | import java.util.* 5 | 6 | object EnumFieldLabelMapper { 7 | fun map(fieldName: String, fieldNamingPolicy: FieldNamingPolicy): String { 8 | return when (fieldNamingPolicy) { 9 | FieldNamingPolicy.IDENTITY -> fieldName 10 | FieldNamingPolicy.UPPER_CAMEL_CASE -> mapUpperCamelCase(fieldName) 11 | FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES -> mapUpperCamelCaseWithSpaces(fieldName) 12 | FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES -> mapLowerCaseWithUnderscores(fieldName) 13 | FieldNamingPolicy.LOWER_CASE_WITH_DASHES -> mapLowerCaseWithDashes(fieldName) 14 | } 15 | } 16 | 17 | private fun map(fieldName: String, separator: String, transformFunc: (String) -> String = { it }): String { 18 | return fieldName.split("_") 19 | .filter { it.isNotBlank() } 20 | .joinToString(separator) { fieldSegment -> 21 | fieldSegment 22 | .toLowerCase(Locale.ENGLISH) 23 | .let(transformFunc) 24 | } 25 | } 26 | 27 | private fun mapUpperCamelCase(fieldName: String): String { 28 | return map(fieldName, "") { it.capitalize() } 29 | } 30 | 31 | private fun mapUpperCamelCaseWithSpaces(fieldName: String): String { 32 | return map(fieldName, " ") { it.capitalize() } 33 | } 34 | 35 | private fun mapLowerCaseWithUnderscores(fieldName: String): String { 36 | return map(fieldName, "_") 37 | } 38 | 39 | private fun mapLowerCaseWithDashes(fieldName: String): String { 40 | return map(fieldName, "-") 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/model/FieldPathFetcher.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.model 2 | 3 | import gsonpath.model.FieldInfo 4 | import gsonpath.util.FieldNamingPolicyMapper 5 | 6 | class FieldPathFetcher( 7 | private val serializedNameFetcher: SerializedNameFetcher, 8 | private val fieldNamingPolicyMapper: FieldNamingPolicyMapper) { 9 | 10 | fun getJsonFieldPath(fieldInfo: FieldInfo, metadata: GsonObjectMetadata): FieldPath { 11 | val serializedName = serializedNameFetcher.getSerializedName(fieldInfo, metadata.flattenDelimiter) 12 | val path = if (serializedName != null && serializedName.isNotBlank()) { 13 | if (metadata.pathSubstitutions.isNotEmpty()) { 14 | 15 | // Check if the serialized name needs any values to be substituted 16 | metadata.pathSubstitutions.fold(serializedName) { fieldPath, substitution -> 17 | fieldPath.replace("{${substitution.original}}", substitution.replacement) 18 | } 19 | 20 | } else { 21 | serializedName 22 | } 23 | 24 | } else { 25 | // Since the serialized annotation wasn't specified, we need to apply the naming policy instead. 26 | fieldNamingPolicyMapper.applyFieldNamingPolicy(metadata.gsonFieldNamingPolicy, fieldInfo.fieldName) 27 | } 28 | 29 | return if (path.contains(metadata.flattenDelimiter)) { 30 | FieldPath.Nested( 31 | if (path.last() == metadata.flattenDelimiter) { 32 | path + fieldInfo.fieldName 33 | } else { 34 | path 35 | } 36 | ) 37 | } else { 38 | FieldPath.Standard(path) 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/model/GsonObjectValidator.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.model 2 | 3 | import com.squareup.javapoet.TypeName 4 | import gsonpath.ProcessingException 5 | import gsonpath.adapter.util.NullableUtil 6 | import gsonpath.model.FieldInfo 7 | import gsonpath.model.FieldType 8 | 9 | class GsonObjectValidator { 10 | 11 | @Throws(ProcessingException::class) 12 | fun validate(fieldInfo: FieldInfo): Result { 13 | val fieldTypeName = fieldInfo.fieldType.typeName 14 | 15 | if (fieldTypeName == TypeName.OBJECT) { 16 | throw ProcessingException("Invalid field type: $fieldTypeName", fieldInfo.element) 17 | } 18 | 19 | // Attempt to find a Nullable or NonNull annotation type. 20 | val isOptional: Boolean = fieldInfo.annotationNames.any { it == "Nullable" } 21 | val isMandatory: Boolean = fieldInfo.annotationNames.any { NullableUtil.isNullableKeyword(it) } 22 | 23 | // Fields cannot use both annotations. 24 | if (isMandatory && isOptional) { 25 | throw ProcessingException("Field cannot have both Mandatory and Optional annotations", fieldInfo.element) 26 | } 27 | 28 | // Primitives should not use either annotation. 29 | if ((fieldInfo.fieldType is FieldType.Primitive) && (isMandatory || isOptional)) { 30 | throw ProcessingException("Primitives should not use NonNull or Nullable annotations", fieldInfo.element) 31 | } 32 | 33 | return when { 34 | isMandatory -> Result.Mandatory 35 | isOptional -> Result.Optional 36 | else -> Result.Standard 37 | } 38 | } 39 | 40 | sealed class Result { 41 | object Mandatory : Result() 42 | object Optional : Result() 43 | object Standard : Result() 44 | } 45 | } -------------------------------------------------------------------------------- /library/src/main/java/gsonpath/GsonPath.java: -------------------------------------------------------------------------------- 1 | package gsonpath; 2 | 3 | import com.google.gson.TypeAdapterFactory; 4 | import gsonpath.annotation.AutoGsonAdapter; 5 | import gsonpath.annotation.AutoGsonAdapterFactory; 6 | 7 | /** 8 | * The primary class to use when using the GsonPath library. 9 | *

10 | * It supplies factories which expose auto generated class created using the {@link AutoGsonAdapter} annotation. 11 | */ 12 | public class GsonPath { 13 | private static final String FACTORY_IMPLEMENTATION_SUFFIX = "Impl"; 14 | 15 | private GsonPath() { 16 | } 17 | 18 | /** 19 | * Creates an instance of an {@link TypeAdapterFactory} implementation class that implements the input interface. 20 | *

21 | * This factory is used to map the auto generated {@link com.google.gson.TypeAdapter} classes created using the 22 | * {@link AutoGsonAdapter} annotation. 23 | *

24 | * Only a single use of reflection is used within the constructor, so it isn't critical to hold onto this reference 25 | * for later usage. 26 | * 27 | * @param clazz the type adatper class to use to find the concrete implementation. Ensure that the interface is 28 | * annotated with {@link AutoGsonAdapterFactory} 29 | * @return a new instance of the {@link TypeAdapterFactory} class 30 | */ 31 | public static TypeAdapterFactory createTypeAdapterFactory(Class clazz) { 32 | String factoryClassName = clazz.getCanonicalName() + FACTORY_IMPLEMENTATION_SUFFIX; 33 | try { 34 | return (TypeAdapterFactory) Class.forName(factoryClassName).newInstance(); 35 | } catch (Exception e) { 36 | throw new IllegalStateException("Unable to instantiate generated TypeAdapterFactory '" + factoryClassName + "'", e); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sample/src/test/java/gsonpath/array/ArrayExampleTest.java: -------------------------------------------------------------------------------- 1 | package gsonpath.array; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import gsonpath.GsonPath; 6 | import gsonpath.TestGsonTypeFactory; 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | public class ArrayExampleTest { 11 | private static final String ARRAY_VALUE = "{\"test1\":[null,1],\"test2\":[null,null,{\"child\":10,\"child2\":20}],\"test3\":[null,null,null,{\"child\":[null,50]}],\"test4\":{\"child\":[null,100]}}"; 12 | 13 | @Test 14 | public void testSerialize() { 15 | GsonBuilder builder = new GsonBuilder(); 16 | builder.registerTypeAdapterFactory(GsonPath.createTypeAdapterFactory(TestGsonTypeFactory.class)); 17 | Gson gson = builder.create(); 18 | 19 | ArrayExample model = new ArrayExample(); 20 | model.plainArray = 1; 21 | model.arrayWithNestedObject = 10; 22 | model.arrayWithNestedObject2 = 20; 23 | model.arrayWithNestedArray = 50; 24 | model.objectWithNestedArray = 100; 25 | 26 | String test = gson.toJson(model); 27 | Assert.assertEquals(ARRAY_VALUE, test); 28 | } 29 | 30 | @Test 31 | public void testDeserialize() { 32 | GsonBuilder builder = new GsonBuilder(); 33 | builder.registerTypeAdapterFactory(GsonPath.createTypeAdapterFactory(TestGsonTypeFactory.class)); 34 | Gson gson = builder.create(); 35 | 36 | ArrayExample vanillaModel = gson.fromJson(ARRAY_VALUE, ArrayExample.class); 37 | 38 | Assert.assertEquals(1, vanillaModel.plainArray); 39 | Assert.assertEquals(10, vanillaModel.arrayWithNestedObject); 40 | Assert.assertEquals(20, vanillaModel.arrayWithNestedObject2); 41 | Assert.assertEquals(50, vanillaModel.arrayWithNestedArray); 42 | Assert.assertEquals(100, vanillaModel.objectWithNestedArray); 43 | } 44 | } -------------------------------------------------------------------------------- /sample/src/test/java/gsonpath/kotlin/DataClassSampleTest.java: -------------------------------------------------------------------------------- 1 | package gsonpath.kotlin; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import gsonpath.GsonPath; 6 | import gsonpath.TestGsonTypeFactory; 7 | import gsonpath.exception.JsonFieldNoKeyException; 8 | import org.junit.Assert; 9 | import org.junit.Test; 10 | 11 | import java.io.InputStream; 12 | import java.io.InputStreamReader; 13 | 14 | import static org.junit.Assert.fail; 15 | 16 | public class DataClassSampleTest { 17 | @Test 18 | public void testWithAllValues() { 19 | DataClassSample model = runTest("DataClassJson_all_values.json"); 20 | 21 | Assert.assertEquals("test", model.getValue1()); 22 | Assert.assertFalse(model.isBooleanTest1()); 23 | Assert.assertNull(model.isBooleanTest2()); 24 | } 25 | 26 | @Test 27 | public void testWithMissingValues() { 28 | try { 29 | runTest("DataClassJson_missing_values.json"); 30 | fail("Exception not triggered"); 31 | } catch (Exception e) { 32 | Assert.assertEquals(JsonFieldNoKeyException.class, e.getClass()); 33 | Assert.assertEquals("Mandatory JSON element 'parent.child.value1' was not found within class " + 34 | "'gsonpath.kotlin.DataClassSample'", e.getMessage()); 35 | } 36 | } 37 | 38 | private DataClassSample runTest(String fileName) { 39 | GsonBuilder builder = new GsonBuilder(); 40 | builder.registerTypeAdapterFactory(GsonPath.createTypeAdapterFactory(TestGsonTypeFactory.class)); 41 | 42 | ClassLoader classLoader = ClassLoader.getSystemClassLoader(); 43 | InputStream resourceAsStream = classLoader.getResourceAsStream(fileName); 44 | 45 | Gson gson = builder.create(); 46 | return gson.fromJson(new InputStreamReader(resourceAsStream), DataClassSample.class); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/unit/adapter/standard/model/MandatoryFieldInfoFactoryTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.unit.adapter.standard.model 2 | 3 | import com.nhaarman.mockitokotlin2.mock 4 | import com.nhaarman.mockitokotlin2.whenever 5 | import gsonpath.adapter.standard.model.GsonArray 6 | import gsonpath.adapter.standard.model.GsonField 7 | import gsonpath.adapter.standard.model.GsonObject 8 | import gsonpath.adapter.standard.model.MandatoryFieldInfoFactory 9 | import gsonpath.simpleGsonObject 10 | import org.junit.Assert 11 | import org.junit.Test 12 | 13 | class MandatoryFieldInfoFactoryTest { 14 | 15 | @Test 16 | fun givenNoRequiredFields_thenExpectEmptyList() { 17 | test(simpleGsonObject("foo", createField(false)), emptyList()) 18 | } 19 | 20 | @Test 21 | fun givenRequiredFields_thenExpectFields() { 22 | val field1 = createField(true) 23 | val field2 = createField(true) 24 | val field3 = createField(true) 25 | val field4 = createField(true) 26 | 27 | val nestedObject = simpleGsonObject("bar", field2) 28 | val array = GsonArray(arrayFields = mapOf(1 to simpleGsonObject("bar", field4), 0 to field3), maxIndex = 2) 29 | val rootObject = GsonObject(fieldMap = mapOf( 30 | "value2" to nestedObject, 31 | "value3" to array, 32 | "value1" to field1 33 | )) 34 | test(rootObject, listOf(field2, field4, field3, field1)) 35 | } 36 | 37 | private fun createField(isRequired: Boolean = false): GsonField { 38 | return mock().apply { whenever(this.isRequired).thenReturn(isRequired) } 39 | } 40 | 41 | private fun test(rootObject: GsonObject, expectedList: List) { 42 | Assert.assertEquals( 43 | expectedList, 44 | MandatoryFieldInfoFactory().createMandatoryFieldsFromGsonObject(rootObject)) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/inheritance/TestInheritance_GsonTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package generator.standard.inheritance; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonWriter; 6 | import gsonpath.annotation.GsonPathGenerated; 7 | import gsonpath.internal.GsonPathTypeAdapter; 8 | import gsonpath.internal.JsonReaderHelper; 9 | 10 | import java.io.IOException; 11 | import java.lang.Integer; 12 | import java.lang.Override; 13 | 14 | @GsonPathGenerated 15 | public final class TestInheritance_GsonTypeAdapter extends GsonPathTypeAdapter { 16 | public TestInheritance_GsonTypeAdapter(Gson gson) { 17 | super(gson); 18 | } 19 | 20 | @Override 21 | public TestInheritance readImpl(JsonReader in) throws IOException { 22 | TestInheritance result = new TestInheritance(); 23 | JsonReaderHelper jsonReaderHelper = new JsonReaderHelper(in, 1, 0); 24 | 25 | while (jsonReaderHelper.handleObject(0, 1)) { 26 | switch (in.nextName()) { 27 | case "Json1": 28 | Integer value_Json1 = gson.getAdapter(Integer.class).read(in); 29 | if (value_Json1 != null) { 30 | result.value1 = value_Json1; 31 | } 32 | break; 33 | 34 | default: 35 | jsonReaderHelper.onObjectFieldNotFound(0); 36 | break; 37 | } 38 | } 39 | 40 | return result; 41 | } 42 | 43 | @Override 44 | public void writeImpl(JsonWriter out, TestInheritance value) throws IOException { 45 | // Begin 46 | out.beginObject(); 47 | int obj0 = value.value1; 48 | out.name("Json1"); 49 | gson.getAdapter(Integer.class).write(out, obj0); 50 | 51 | // End 52 | out.endObject(); 53 | } 54 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/field_annotations/exclude/TestExclude_GsonTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package generator.standard.field_annotations.exclude; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonWriter; 6 | import gsonpath.annotation.GsonPathGenerated; 7 | import gsonpath.internal.GsonPathTypeAdapter; 8 | import gsonpath.internal.JsonReaderHelper; 9 | 10 | import java.io.IOException; 11 | import java.lang.Integer; 12 | import java.lang.Override; 13 | 14 | @GsonPathGenerated 15 | public final class TestExclude_GsonTypeAdapter extends GsonPathTypeAdapter { 16 | public TestExclude_GsonTypeAdapter(Gson gson) { 17 | super(gson); 18 | } 19 | 20 | @Override 21 | public TestExclude readImpl(JsonReader in) throws IOException { 22 | TestExclude result = new TestExclude(); 23 | JsonReaderHelper jsonReaderHelper = new JsonReaderHelper(in, 1, 0); 24 | 25 | while (jsonReaderHelper.handleObject(0, 1)) { 26 | switch (in.nextName()) { 27 | case "element1": 28 | Integer value_element1 = gson.getAdapter(Integer.class).read(in); 29 | if (value_element1 != null) { 30 | result.element1 = value_element1; 31 | } 32 | break; 33 | 34 | default: 35 | jsonReaderHelper.onObjectFieldNotFound(0); 36 | break; 37 | 38 | } 39 | } 40 | return result; 41 | } 42 | 43 | @Override 44 | public void writeImpl(JsonWriter out, TestExclude value) throws IOException { 45 | // Begin 46 | out.beginObject(); 47 | int obj0 = value.element1; 48 | out.name("element1"); 49 | gson.getAdapter(Integer.class).write(out, obj0); 50 | 51 | // End 52 | out.endObject(); 53 | } 54 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/properties/DelimiterTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.properties 2 | 3 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 4 | import gsonpath.integration.common.TestCriteria 5 | import org.junit.Test 6 | 7 | class DelimiterTest { 8 | 9 | @Test 10 | fun testStandardDelimiter() { 11 | assertGeneratedContent(TestCriteria("generator/standard/delimiter/standard", 12 | 13 | absoluteSourceNames = listOf( 14 | "generator/standard/TestGsonTypeFactory.java"), 15 | 16 | relativeSourceNames = listOf( 17 | "TestStandardDelimiter.java"), 18 | 19 | relativeGeneratedNames = listOf( 20 | "TestStandardDelimiter_GsonTypeAdapter.java") 21 | )) 22 | } 23 | 24 | @Test 25 | fun testCustomDelimiter() { 26 | assertGeneratedContent(TestCriteria("generator/standard/delimiter/custom", 27 | 28 | absoluteSourceNames = listOf( 29 | "generator/standard/TestGsonTypeFactory.java"), 30 | 31 | relativeSourceNames = listOf( 32 | "TestCustomDelimiter.java"), 33 | 34 | relativeGeneratedNames = listOf( 35 | "TestCustomDelimiter_GsonTypeAdapter.java") 36 | )) 37 | } 38 | 39 | @Test 40 | fun testMultipleDelimiters() { 41 | assertGeneratedContent(TestCriteria("generator/standard/delimiter/multiple", 42 | 43 | absoluteSourceNames = listOf( 44 | "generator/standard/TestGsonTypeFactory.java"), 45 | 46 | relativeSourceNames = listOf( 47 | "TestMultipleDelimiters.java"), 48 | 49 | relativeGeneratedNames = listOf( 50 | "TestMultipleDelimiters_GsonTypeAdapter.java") 51 | )) 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /compiler/standard/src/test/java/gsonpath/integration/properties/SubstitutionTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.integration.properties 2 | 3 | import com.google.common.truth.Truth.assertAbout 4 | import com.google.testing.compile.JavaFileObjects 5 | import com.google.testing.compile.JavaSourcesSubjectFactory 6 | import gsonpath.GsonProcessor 7 | import gsonpath.integration.common.GeneratorTester.assertGeneratedContent 8 | import gsonpath.integration.common.TestCriteria 9 | import org.junit.Test 10 | 11 | class SubstitutionTest { 12 | @Test 13 | fun testValidSubstitution() { 14 | assertGeneratedContent(TestCriteria("generator/standard/substitution/valid", 15 | 16 | absoluteSourceNames = listOf( 17 | "generator/standard/TestGsonTypeFactory.java"), 18 | 19 | relativeSourceNames = listOf( 20 | "TestSubstitutionBase.java", 21 | "TestSubstitutionImpl1.java", 22 | "TestSubstitutionImpl2.java"), 23 | 24 | relativeGeneratedNames = listOf( 25 | "TestSubstitutionImpl1_GsonTypeAdapter.java", 26 | "TestSubstitutionImpl2_GsonTypeAdapter.java") 27 | )) 28 | } 29 | 30 | @Test 31 | fun testSubstitutionError_duplicateKeys() { 32 | val source = JavaFileObjects.forResource("generator/standard/substitution/errors/TestSubstitutionError_DuplicateKeys.java") 33 | 34 | assertAbout(JavaSourcesSubjectFactory.javaSources()) 35 | .that(listOf( 36 | JavaFileObjects.forResource("generator/standard/TestGsonTypeFactory.java"), 37 | source 38 | )) 39 | .processedWith(GsonProcessor()) 40 | .failsToCompile() 41 | .withErrorContaining("PathSubstitution original values must be unique") 42 | .`in`(source) 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /compiler/standard/src/main/java/gsonpath/adapter/standard/adapter/properties/AdapterCommonPropertiesFactory.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.adapter.standard.adapter.properties 2 | 3 | import com.google.gson.FieldNamingPolicy 4 | import gsonpath.GsonFieldValidationType 5 | import gsonpath.LazyFactoryMetadata 6 | import gsonpath.annotation.AutoGsonAdapter 7 | import javax.lang.model.element.TypeElement 8 | 9 | class AdapterCommonPropertiesFactory { 10 | 11 | fun create( 12 | modelElement: TypeElement, 13 | adapterAnnotation: AutoGsonAdapter, 14 | lazyFactoryMetadata: LazyFactoryMetadata): AdapterCommonProperties { 15 | 16 | val propertyFetcher = PropertyFetcher(modelElement) 17 | 18 | val flattenDelimiter = propertyFetcher.getProperty("flattenDelimiter", 19 | adapterAnnotation.flattenDelimiter.toTypedArray(), 20 | lazyFactoryMetadata.annotation.flattenDelimiter) 21 | 22 | val serializeNulls = propertyFetcher.getProperty("serializeNulls", 23 | adapterAnnotation.serializeNulls.toTypedArray(), 24 | lazyFactoryMetadata.annotation.serializeNulls) 25 | 26 | val fieldNamingPolicy = propertyFetcher.getProperty("fieldNamingPolicy", 27 | adapterAnnotation.fieldNamingPolicy, 28 | lazyFactoryMetadata.annotation.fieldNamingPolicy) 29 | 30 | val fieldValidationType = propertyFetcher.getProperty("fieldValidationType", 31 | adapterAnnotation.fieldValidationType, 32 | lazyFactoryMetadata.annotation.fieldValidationType) 33 | 34 | return AdapterCommonProperties(flattenDelimiter, serializeNulls, fieldNamingPolicy, fieldValidationType) 35 | } 36 | } 37 | 38 | data class AdapterCommonProperties( 39 | val flattenDelimiter: Char, 40 | val serializeNulls: Boolean, 41 | val fieldNamingPolicy: FieldNamingPolicy, 42 | val fieldValidationType: GsonFieldValidationType) -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/interf/java8/TestJava8Interface_GsonTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package generator.interf.java8; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonWriter; 6 | import gsonpath.annotation.GsonPathGenerated; 7 | import gsonpath.internal.GsonPathTypeAdapter; 8 | import gsonpath.internal.GsonUtil; 9 | import gsonpath.internal.JsonReaderHelper; 10 | 11 | import java.io.IOException; 12 | import java.lang.Integer; 13 | import java.lang.Override; 14 | 15 | @GsonPathGenerated 16 | public final class TestJava8Interface_GsonTypeAdapter extends GsonPathTypeAdapter { 17 | public TestJava8Interface_GsonTypeAdapter(Gson gson) { 18 | super(gson); 19 | } 20 | 21 | @Override 22 | public TestJava8Interface readImpl(JsonReader in) throws IOException { 23 | Integer value_value1 = null; 24 | JsonReaderHelper jsonReaderHelper = new JsonReaderHelper(in, 1, 0); 25 | 26 | while (jsonReaderHelper.handleObject(0, 1)) { 27 | switch (in.nextName()) { 28 | case "value1": 29 | value_value1 = gson.getAdapter(Integer.class).read(in); 30 | break; 31 | 32 | default: 33 | jsonReaderHelper.onObjectFieldNotFound(0); 34 | break; 35 | 36 | } 37 | } 38 | return new TestJava8Interface_GsonPathModel( 39 | value_value1); 40 | } 41 | 42 | @Override 43 | public void writeImpl(JsonWriter out, TestJava8Interface value) throws IOException { 44 | // Begin 45 | out.beginObject(); 46 | Integer obj0 = value.getValue1(); 47 | if (obj0 != null) { 48 | out.name("value1"); 49 | GsonUtil.writeWithGenericAdapter(gson, obj0.getClass(), out, obj0); 50 | } 51 | 52 | // End 53 | out.endObject(); 54 | } 55 | } -------------------------------------------------------------------------------- /library-kt/src/test/java/gsonpath/result/GsonResultListTest.kt: -------------------------------------------------------------------------------- 1 | package gsonpath.result 2 | 3 | import com.google.gson.GsonBuilder 4 | import com.google.gson.JsonSyntaxException 5 | import com.google.gson.reflect.TypeToken 6 | import gsonpath.GsonPathTypeAdapterFactoryKt 7 | import gsonpath.GsonResult 8 | import gsonpath.GsonResultList 9 | import org.hamcrest.CustomTypeSafeMatcher 10 | import org.junit.Assert.assertEquals 11 | import org.junit.Assert.assertThat 12 | import org.junit.Test 13 | import java.io.InputStreamReader 14 | 15 | class GsonResultListTest { 16 | @Test 17 | fun testUsingGsonSafeArrayList() { 18 | val gson = GsonBuilder() 19 | .registerTypeAdapterFactory(GsonPathTypeAdapterFactoryKt()) 20 | .create() 21 | 22 | val resourceAsStream = ClassLoader 23 | .getSystemClassLoader() 24 | .getResourceAsStream("sample.json") 25 | 26 | val typesList: GsonResultList = gson.fromJson>( 27 | InputStreamReader(resourceAsStream!!), 28 | object : TypeToken>() {}.type 29 | ) 30 | 31 | assertEquals(4, typesList.size) 32 | assertEquals(GsonResult.Success(1), typesList[0]) 33 | assertThat(typesList[1], createFailureMatcher("For input string: \"a\"")) 34 | assertThat(typesList[2], createFailureMatcher("For input string: \"b\"")) 35 | assertEquals(GsonResult.Success(4), typesList[3]) 36 | } 37 | 38 | private fun createFailureMatcher(message: String) = object : CustomTypeSafeMatcher>("") { 39 | override fun matchesSafely(item: GsonResult): Boolean { 40 | return (item as GsonResult.Failure).exception.let { 41 | it is JsonSyntaxException && 42 | it.cause!!.message == message && 43 | it.cause is NumberFormatException 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/nested_class/TestNestedClass_Nested_GsonTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package generator.standard.nested_class; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonWriter; 6 | import gsonpath.annotation.GsonPathGenerated; 7 | import gsonpath.internal.GsonPathTypeAdapter; 8 | import gsonpath.internal.JsonReaderHelper; 9 | 10 | import java.io.IOException; 11 | import java.lang.Integer; 12 | import java.lang.Override; 13 | 14 | @GsonPathGenerated 15 | public final class TestNestedClass_Nested_GsonTypeAdapter extends GsonPathTypeAdapter { 16 | public TestNestedClass_Nested_GsonTypeAdapter(Gson gson) { 17 | super(gson); 18 | } 19 | 20 | @Override 21 | public TestNestedClass.Nested readImpl(JsonReader in) throws IOException { 22 | TestNestedClass.Nested result = new TestNestedClass.Nested(); 23 | JsonReaderHelper jsonReaderHelper = new JsonReaderHelper(in, 1, 0); 24 | 25 | while (jsonReaderHelper.handleObject(0, 1)) { 26 | switch (in.nextName()) { 27 | case "value1": 28 | Integer value_value1 = gson.getAdapter(Integer.class).read(in); 29 | if (value_value1 != null) { 30 | result.value1 = value_value1; 31 | } 32 | break; 33 | 34 | default: 35 | jsonReaderHelper.onObjectFieldNotFound(0); 36 | break; 37 | 38 | } 39 | } 40 | return result; 41 | } 42 | 43 | @Override 44 | public void writeImpl(JsonWriter out, TestNestedClass.Nested value) throws IOException { 45 | // Begin 46 | out.beginObject(); 47 | int obj0 = value.value1; 48 | out.name("value1"); 49 | gson.getAdapter(Integer.class).write(out, obj0); 50 | 51 | // End 52 | out.endObject(); 53 | } 54 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/gson_sub_type/one_argument/TypeGsonSubType_GsonTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package generator.gson_sub_type.one_argument; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonElement; 5 | import com.google.gson.TypeAdapter; 6 | import com.google.gson.internal.Streams; 7 | import com.google.gson.stream.JsonReader; 8 | import com.google.gson.stream.JsonWriter; 9 | import gsonpath.annotation.GsonPathGenerated; 10 | import gsonpath.internal.GsonPathTypeAdapter; 11 | 12 | import java.io.IOException; 13 | import java.lang.Class; 14 | import java.lang.Override; 15 | import java.lang.String; 16 | 17 | @GsonPathGenerated 18 | public final class TypeGsonSubType_GsonTypeAdapter extends GsonPathTypeAdapter { 19 | 20 | public TypeGsonSubType_GsonTypeAdapter(Gson gson) { 21 | super(gson); 22 | } 23 | 24 | @Override 25 | public TypeGsonSubType readImpl(JsonReader in) throws IOException { 26 | JsonElement jsonElement = Streams.parse(in); 27 | 28 | JsonElement subTypeElement0_jsonElement = jsonElement.getAsJsonObject().get("type"); 29 | final String subTypeElement0; 30 | if (subTypeElement0_jsonElement == null || subTypeElement0_jsonElement.isJsonNull()) { 31 | subTypeElement0 = null; 32 | } else { 33 | subTypeElement0 = gson.getAdapter(String.class).fromJsonTree(subTypeElement0_jsonElement); 34 | } 35 | 36 | Class delegateClass = TypeGsonSubType.getSubType1(subTypeElement0); 37 | if (delegateClass == null) { 38 | return null; 39 | } 40 | TypeGsonSubType result = gson.getAdapter(delegateClass).fromJsonTree(jsonElement); 41 | return result; 42 | } 43 | 44 | @Override 45 | public void writeImpl(JsonWriter out, TypeGsonSubType value) throws IOException { 46 | TypeAdapter delegateAdapter = gson.getAdapter(value.getClass()); 47 | delegateAdapter.write(out, value); 48 | } 49 | } -------------------------------------------------------------------------------- /compiler/standard/src/test/resources/generator/standard/naming_policy/identity/TestNamePolicyIdentity_GsonTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package generator.standard.naming_policy.identity; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonWriter; 6 | import gsonpath.annotation.GsonPathGenerated; 7 | import gsonpath.internal.GsonPathTypeAdapter; 8 | import gsonpath.internal.JsonReaderHelper; 9 | 10 | import java.io.IOException; 11 | import java.lang.Integer; 12 | import java.lang.Override; 13 | 14 | @GsonPathGenerated 15 | public final class TestNamePolicyIdentity_GsonTypeAdapter extends GsonPathTypeAdapter { 16 | public TestNamePolicyIdentity_GsonTypeAdapter(Gson gson) { 17 | super(gson); 18 | } 19 | 20 | @Override 21 | public TestNamePolicyIdentity readImpl(JsonReader in) throws IOException { 22 | TestNamePolicyIdentity result = new TestNamePolicyIdentity(); 23 | JsonReaderHelper jsonReaderHelper = new JsonReaderHelper(in, 1, 0); 24 | 25 | while (jsonReaderHelper.handleObject(0, 1)) { 26 | switch (in.nextName()) { 27 | case "testValue": 28 | Integer value_testValue = gson.getAdapter(Integer.class).read(in); 29 | if (value_testValue != null) { 30 | result.testValue = value_testValue; 31 | } 32 | break; 33 | 34 | default: 35 | jsonReaderHelper.onObjectFieldNotFound(0); 36 | break; 37 | 38 | } 39 | } 40 | return result; 41 | } 42 | 43 | @Override 44 | public void writeImpl(JsonWriter out, TestNamePolicyIdentity value) throws IOException { 45 | // Begin 46 | out.beginObject(); 47 | int obj0 = value.testValue; 48 | out.name("testValue"); 49 | gson.getAdapter(Integer.class).write(out, obj0); 50 | 51 | // End 52 | out.endObject(); 53 | } 54 | } --------------------------------------------------------------------------------