diff --git a/.github/ISSUE_TEMPLATE/add-company-logo-to-users.md b/.github/ISSUE_TEMPLATE/add-company-logo-to-users.md deleted file mode 100644 index 8cfc728..0000000 --- a/.github/ISSUE_TEMPLATE/add-company-logo-to-users.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -name: Add company logo to users -about: 'If you’re using Arrow in Production, submit this issue to get your logo added - to the Arrow_kt.io website under the list of users! ' -title: "[Add company logo]" -labels: Arrow in Production -assignees: MaureenElsberry - ---- - -**Company Name:** - -**Website:** - -**Logo:** - -Please upload a high-res logo of either .svg or .png to this issue. - -- [ ] By checking this box, I’m confirming that I have permission to add this company to the public list of users. - -**Optional Information:** - -Tell us a bit on how you’re using Arrow! We’d love to hear it: diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..0bad26c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG] Short description" +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Environment (please complete the following information):** + - Kotlin version [eg. 1.3.61]: + - [Kotlin Intellij IDEA plugin version](https://plugins.jetbrains.com/plugin/6954-kotlin/versions) [eg. 1.3.61-release-IJ2019.3-1]: +- Intellij IDEA version: + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index ff97cd6..bbcbbe7 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,12 +1,20 @@ --- name: Feature request -about: What would you like to see in Arrow? -title: [Request] +about: Suggest an idea for this project +title: '' labels: '' -assignees: Maintainers +assignees: '' --- -What version are you currently using? +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -What would you like to see? +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/build_arrow-integrations.yml b/.github/workflows/build_arrow-integrations.yml deleted file mode 100644 index 4e9084b..0000000 --- a/.github/workflows/build_arrow-integrations.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: "arrow-integrations: build" - -on: pull_request - -jobs: - arrow-integrations_build: - - env: - JAVA_OPTS: -Xms512m -Xmx1024m - - runs-on: macos-latest - timeout-minutes: 90 - - steps: - - uses: actions/checkout@v2 - - name: Validate Gradle Wrapper - uses: gradle/wrapper-validation-action@v1 - - name: Build - run: | - ./gradlew build - - name: Prepare test reports - if: ${{ always() }} - run: | - mkdir test-reports - for report in `ls -d ./**/build/reports/tests/test`; do - arrow_module=$(echo $report | cut -d/ -f2) - cp -r $report test-reports/$arrow_module - done - - name: Make test reports available to download - if: ${{ always() }} - uses: actions/upload-artifact@v1 - with: - name: test-reports - path: test-reports diff --git a/.github/workflows/build_doc_arrow-integrations.yml b/.github/workflows/build_doc_arrow-integrations.yml deleted file mode 100644 index 73cc87d..0000000 --- a/.github/workflows/build_doc_arrow-integrations.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: "arrow-integrations: build documentation" - -on: pull_request - -jobs: - arrow-integrations_build_documentation: - - env: - JAVA_OPTS: -Xms512m -Xmx1024m - - runs-on: macos-latest - timeout-minutes: 90 - - steps: - - uses: actions/checkout@v2 - - name: Generate API doc - run: ./gradlew dokka - - name: Validation - run: ./gradlew :arrow-docs:runAnk diff --git a/.github/workflows/generate-alpha-tag.yaml b/.github/workflows/generate-alpha-tag.yaml new file mode 100644 index 0000000..fef9b1b --- /dev/null +++ b/.github/workflows/generate-alpha-tag.yaml @@ -0,0 +1,59 @@ +name: generate-alpha-tag + +on: + push: + branches: + - main + +env: + GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.parallel=false -Dorg.gradle.jvmargs="-Xmx5g -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Java + uses: actions/setup-java@v3.0.0 + with: + distribution: 'adopt' + java-version: '15' + + - name: Gradle build + run: ./gradlew --full-stacktrace build "-Psemver.stage=alpha" + + - name: Stop Gradle daemons + run: ./gradlew --stop + + generate-alpha-tag: + runs-on: ubuntu-latest + + needs: + - build + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + token: ${{ secrets.TOKEN_GITHUB_ACTION }} + + - name: Set up Java + uses: actions/setup-java@v3.0.0 + with: + distribution: 'adopt' + java-version: '15' + + - name: Generate Tag + run: ./gradlew --full-stacktrace createSemverTag "-Psemver.stage=alpha" + + - name: Push + run: git push --follow-tags + + - name: Stop Gradle daemons + run: ./gradlew --stop diff --git a/.github/workflows/generate-tag.yaml b/.github/workflows/generate-tag.yaml new file mode 100644 index 0000000..3388864 --- /dev/null +++ b/.github/workflows/generate-tag.yaml @@ -0,0 +1,80 @@ +name: generate-tag + +on: + workflow_dispatch: + if: github.ref == 'refs/heads/main' + inputs: + stage: + description: 'Stage' + required: true + default: 'auto' + type: choice + options: + - 'alpha' + - 'beta' + - 'rc' + - 'final' + - 'auto' + scope: + description: 'Scope' + required: true + default: 'auto' + type: choice + options: + - 'patch' + - 'minor' + - 'major' + - 'auto' + +env: + GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.parallel=false -Dorg.gradle.jvmargs="-Xmx5g -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Java + uses: actions/setup-java@v3.0.0 + with: + distribution: 'adopt' + java-version: '15' + + - name: Gradle build + run: ./gradlew --full-stacktrace build "-Psemver.scope=${{ github.event.inputs.scope }}" "-Psemver.stage=${{ github.event.inputs.stage }}" + + - name: Stop Gradle daemons + run: ./gradlew --stop + + generate-tag: + runs-on: ubuntu-latest + + needs: + - build + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + token: ${{ secrets.TOKEN_GITHUB_ACTION }} + + - name: Set up Java + uses: actions/setup-java@v3.0.0 + with: + distribution: 'adopt' + java-version: '15' + + - name: Generate Tag + run: ./gradlew --full-stacktrace createSemverTag "-Psemver.scope=${{ github.event.inputs.scope }}" "-Psemver.stage=${{ github.event.inputs.stage }}" + + - name: Push + run: git push --follow-tags + + - name: Stop Gradle daemons + run: ./gradlew --stop \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..96d61f9 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,93 @@ +name: Publish Artifacts + +on: + push: + tags: + - '**' + +env: + SONATYPE_USER: ${{ secrets.SONATYPE_USER }} + SONATYPE_PWD: ${{ secrets.SONATYPE_PWD }} + ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_SECRET }} + ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.PGP_PASSPHRASE }} + OSS_USER: '${{ secrets.OSS_USER }}' + OSS_TOKEN: '${{ secrets.OSS_TOKEN }}' + OSS_STAGING_PROFILE_ID: '${{ secrets.OSS_STAGING_PROFILE_ID }}' + SIGNING_KEY_NAME: '${{ secrets.SIGNING_KEY_NAME }}' + SIGNING_KEY_ID: '${{ secrets.SIGNING_KEY_ID }}' + SIGNING_KEY_PASSPHRASE: '${{ secrets.SIGNING_KEY_PASSPHRASE }}' + SIGNING_KEY: '${{ secrets.SIGNING_KEY }}' + GRADLE_PUBLISH_KEY: '${{ secrets.GRADLE_PUBLISH_KEY }}' + GRADLE_PUBLISH_SECRET: '${{ secrets.GRADLE_PUBLISH_SECRET }}' + +jobs: + build: + + runs-on: ubuntu-latest + timeout-minutes: 30 + + outputs: + integrations-version: ${{ steps.get-integrations-version.outputs.integrations-version }} + + steps: + - uses: actions/checkout@v3.0.0 + with: + fetch-depth: 0 + + - uses: actions/setup-java@v3.0.0 + with: + distribution: 'adopt' + java-version: '15' + + - name: Build and test with Gradle + uses: gradle/gradle-build-action@v2.1.4 + with: + arguments: build --scan --stacktrace + + - id: get-integrations-version + name: Get Arrow Integrations version + run: | + ./gradlew + echo "::set-output name=integrations-version::$(head -n 1 build/semver/version.txt)" + + - name: Upload reports + uses: actions/upload-artifact@v3.0.0 + with: + name: 'reports-${{ matrix.os }}' + path: '**/build/reports/**' + + - name: Stop Gradle daemons + run: ./gradlew --stop + + publish: + needs: build + env: + JAVA_OPTS: -Xms512m -Xmx1024m + + runs-on: macos-11 + + steps: + - uses: actions/checkout@v3.0.0 + + - uses: actions/setup-java@v3.0.0 + with: + distribution: 'adopt' + java-version: '15' + cache: 'gradle' + + - name: Publish alpha/beta/rc artifacts + if: | + contains(needs.build.outputs.integrations-version, 'alpha') || + contains(needs.build.outputs.integrations-version, 'beta') || + contains(needs.build.outputs.integrations-version, 'rc') + run: ./gradlew --full-stacktrace publishToSonatype closeAndReleaseSonatypeStagingRepository + + - name: Publish final artifacts + if: | + !contains(needs.build.outputs.integrations-version, 'alpha') && + !contains(needs.build.outputs.integrations-version, 'beta') && + !contains(needs.build.outputs.integrations-version, 'rc') + run: ./gradlew --full-stacktrace publishToSonatype closeAndReleaseSonatypeStagingRepository + + - name: Stop Gradle daemons + run: ./gradlew --stop diff --git a/.github/workflows/publish_arrow-integrations.yml b/.github/workflows/publish_arrow-integrations.yml deleted file mode 100644 index 697b3f7..0000000 --- a/.github/workflows/publish_arrow-integrations.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: "Publish libraries" - -on: - push: - branches: - - main - -jobs: - publish: - - env: - BASEDIR: ${{github.workspace}} - JAVA_OPTS: -Xms512m -Xmx1024m - SONATYPE_USER: ${{ secrets.SONATYPE_USER }} - SONATYPE_PWD: ${{ secrets.SONATYPE_PWD }} - ORG_GRADLE_PROJECT_signingKey: ${{ secrets.ORG_GRADLE_PROJECT_signingKey }} - ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.ORG_GRADLE_PROJECT_signingPassword }} - - runs-on: macos-latest - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: "Setup" - run: brew install grep - - name: "Set env" - run: | - echo "$JAVA_HOME_8_X64/bin" >> $GITHUB_PATH - echo "JAVA_HOME=$JAVA_HOME_8_X64" >> $GITHUB_ENV - LATEST_PUBLISHED_VERSION=$(curl -L https://repo1.maven.org/maven2/io/arrow-kt/arrow-integrations-jackson-module/maven-metadata.xml | ggrep -oP '\K[^<]*') - if [ "$LATEST_PUBLISHED_VERSION" == "" ]; then exit 1; fi - RELEASE_VERSION=$(grep LATEST_VERSION $BASEDIR/gradle.properties | cut -d= -f2) - echo "LATEST_PUBLISHED_VERSION=$LATEST_PUBLISHED_VERSION" >> $GITHUB_ENV - echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_ENV - echo "NEW_RELEASE_VERSION_EXISTS="$([ "$LATEST_PUBLISHED_VERSION" == "$RELEASE_VERSION" ] && echo '0' || echo '1') >> $GITHUB_ENV - - name: "Show env" - run: | - echo "LATEST_PUBLISHED_VERSION: $LATEST_PUBLISHED_VERSION" - echo "RELEASE_VERSION: $RELEASE_VERSION" - echo "NEW_RELEASE_VERSION_EXISTS: $NEW_RELEASE_VERSION_EXISTS" - - name: "Update configuration when release" - if: env.NEW_RELEASE_VERSION_EXISTS == '1' - run: | - perl -pe "s/^VERSION_NAME=.*/VERSION_NAME=$RELEASE_VERSION/g" -i $BASEDIR/gradle.properties - perl -pe "s/^org.gradle.parallel=.*/org.gradle.parallel=false/g" -i $BASEDIR/gradle.properties - - name: "Publish" - run: | - ./gradlew publish - echo "$(cat $BASEDIR/gradle.properties | grep VERSION_NAME | cut -d'=' -f2) deployed!" - #- name: "Create tag" - # if: env.NEW_RELEASE_VERSION_EXISTS == '1' - # run: | - # git remote set-url origin https://arrow-kt:$GITHUB_TOKEN@github.com/arrow-kt/arrow-integrations.git - # git config --global user.email "arrow-kt@users.noreply.github.com" - # git config --global user.name "arrow-kt" - # git tag -a $RELEASE_VERSION -m "Release $RELEASE_VERSION" - # git push origin $RELEASE_VERSION diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 0000000..d1b40d0 --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,61 @@ +name: Build Artifacts for PR + +on: pull_request + +env: + JAVA_OPTS: -Xms512m -Xmx1024m + GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.configureondemand=true -Dorg.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" + + +jobs: + arrow-integrations_build: + + runs-on: ubuntu-latest + timeout-minutes: 20 + + steps: + - uses: actions/checkout@v3.0.0 + with: + fetch-depth: 0 + + - uses: actions/setup-java@v3.0.0 + with: + distribution: 'adopt' + java-version: '15' + + - name: Build and test with Gradle + uses: gradle/gradle-build-action@v2.1.4 + with: + arguments: build --scan --stacktrace + + - name: Upload reports + uses: actions/upload-artifact@v3.0.0 + with: + name: 'reports-${{ matrix.os }}' + path: '**/build/reports/**' + + - name: Stop Gradle daemons + run: ./gradlew --stop + + update_api: + runs-on: ubuntu-latest + timeout-minutes: 20 + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Build + uses: gradle/gradle-build-action@v2.1.4 + with: + arguments: apiDump + + - name: Stop Gradle daemons + run: ./gradlew --stop + + - name: "Commit new API files" + uses: stefanzweifel/git-auto-commit-action@v4.14.0 + with: + commit_message: Update API files + file_pattern: /**/api/*.api diff --git a/README.md b/README.md index 0a3f1bb..3fbb07e 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,11 @@ # Arrow Integrations [![Maven Central](https://img.shields.io/maven-central/v/io.arrow-kt/arrow-integrations-jackson-module?color=4caf50&label=latest%20release)](https://maven-badges.herokuapp.com/maven-central/io.arrow-kt/arrow-integrations-jackson-module) -[![Latest snapshot](https://img.shields.io/maven-metadata/v?label=latest%20snapshot&metadataUrl=https%3A%2F%2Foss.sonatype.org%2Fservice%2Flocal%2Frepositories%2Fsnapshots%2Fcontent%2Fio%2Farrow-kt%2Farrow-integrations-jackson-module%2Fmaven-metadata.xml)](https://oss.sonatype.org/service/local/repositories/snapshots/content/io/arrow-kt/) [![Arrow Core logo](https://raw.githubusercontent.com/arrow-kt/arrow-site/master/docs/img/core/arrow-core-brand-sidebar.svg?sanitize=true)](https://arrow-kt.io) Λrrow Integrations is part of [**Λrrow**](https://arrow-kt.io). -Global properties come from [**arrow**](https://github.com/arrow-kt/arrow) repository. - ## Jackson Module Include `arrow-integrations-jackson` in your gradle project: @@ -147,4 +144,4 @@ Jackson support for arrow data type serialization / deserialization can similarl install(ContentNegotiation) { register(ContentType.Application.Json, JacksonConverter(JsonMapper.mapper)) } -``` \ No newline at end of file +``` diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index c494217..0000000 --- a/RELEASE.md +++ /dev/null @@ -1,30 +0,0 @@ -## Release flow - -## 1. Create a pull request - -Prepare a pull request with these changes: - -1. Update versions in `gradle.properties`. For instance, the release version will be `0.10.5` and the next SNAPSHOT version will be `0.11.0-SNAPSHOT`: -``` -VERSION_NAME=0.11.0-SNAPSHOT -LATEST_VERSION=0.10.5 -``` - -When merging that pull request, this thing will happen automatically: - -* New RELEASE version will be published for all the Arrow libraries into Sonatype staging repository. - -These changes should be done manually now: - -* Create a tag with the RELEASE version. -* Create a release associated to that tag. - -## 2. Close and release - -Then, close and release the Sonatype repository to sync with Maven Central: - -1. Login to https://oss.sonatype.org/ > `Staging repositories` -2. Check the content of the new staging repository -3. Select the staging repository and **Close** (it will check if the content meet the requirements) -4. Select the staging repository and **Release** to sync with Maven Central -5. **Drop** and repeat if there are issues. diff --git a/arrow-docs/build.gradle b/arrow-docs/build.gradle deleted file mode 100644 index 215b5b4..0000000 --- a/arrow-docs/build.gradle +++ /dev/null @@ -1,38 +0,0 @@ -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath "io.arrow-kt:arrow-ank-gradle:$ARROW_VERSION" - } -} - -plugins { - id "org.jetbrains.kotlin.jvm" - id "org.jetbrains.kotlin.kapt" - id "org.jlleitschuh.gradle.ktlint" -} - -apply from: "$SUB_PROJECT" - -dependencies { - runtimeOnly project(':arrow-integrations-jackson-module') -} - -apply plugin: 'ank-gradle-plugin' - -ank { - source = file("${rootDir}/build/documentation") - target = file("${rootDir}/build/_documentation") - classpath = sourceSets.main.runtimeClasspath -} - -task copyREADME(type: Copy) { - from "${rootDir}/README.md" - into "${rootDir}/build/documentation" -} - -afterEvaluate { - runAnk.dependsOn 'copyREADME' - runAnk.mustRunAfter 'copyREADME' -} \ No newline at end of file diff --git a/arrow-docs/gradle.properties b/arrow-docs/gradle.properties deleted file mode 100644 index 263a68d..0000000 --- a/arrow-docs/gradle.properties +++ /dev/null @@ -1,5 +0,0 @@ -# Maven publishing configuration -POM_NAME=Arrow-Core-Docs -POM_ARTIFACT_ID=arrow-core-docs -POM_PACKAGING=jar -kapt.incremental.apt=false diff --git a/arrow-integrations-jackson-module/api/arrow-integrations-jackson-module.api b/arrow-integrations-jackson-module/api/arrow-integrations-jackson-module.api new file mode 100644 index 0000000..b838bb4 --- /dev/null +++ b/arrow-integrations-jackson-module/api/arrow-integrations-jackson-module.api @@ -0,0 +1,207 @@ +public final class arrow/integrations/jackson/module/ArrowModuleKt { + public static final fun registerArrowModule (Lcom/fasterxml/jackson/databind/ObjectMapper;Larrow/integrations/jackson/module/EitherModuleConfig;Larrow/integrations/jackson/module/ValidatedModuleConfig;Larrow/integrations/jackson/module/IorModuleConfig;)Lcom/fasterxml/jackson/databind/ObjectMapper; + public static synthetic fun registerArrowModule$default (Lcom/fasterxml/jackson/databind/ObjectMapper;Larrow/integrations/jackson/module/EitherModuleConfig;Larrow/integrations/jackson/module/ValidatedModuleConfig;Larrow/integrations/jackson/module/IorModuleConfig;ILjava/lang/Object;)Lcom/fasterxml/jackson/databind/ObjectMapper; +} + +public final class arrow/integrations/jackson/module/EitherDeserializerResolver : com/fasterxml/jackson/databind/deser/Deserializers$Base { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun findBeanDeserializer (Lcom/fasterxml/jackson/databind/JavaType;Lcom/fasterxml/jackson/databind/DeserializationConfig;Lcom/fasterxml/jackson/databind/BeanDescription;)Lcom/fasterxml/jackson/databind/JsonDeserializer; +} + +public final class arrow/integrations/jackson/module/EitherModule : com/fasterxml/jackson/databind/module/SimpleModule { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun setupModule (Lcom/fasterxml/jackson/databind/Module$SetupContext;)V +} + +public final class arrow/integrations/jackson/module/EitherModuleConfig { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/lang/String; + public final fun copy (Ljava/lang/String;Ljava/lang/String;)Larrow/integrations/jackson/module/EitherModuleConfig; + public static synthetic fun copy$default (Larrow/integrations/jackson/module/EitherModuleConfig;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Larrow/integrations/jackson/module/EitherModuleConfig; + public fun equals (Ljava/lang/Object;)Z + public final fun getLeftFieldName ()Ljava/lang/String; + public final fun getRightFieldName ()Ljava/lang/String; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class arrow/integrations/jackson/module/EitherSerializerResolver : com/fasterxml/jackson/databind/ser/Serializers$Base { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun findSerializer (Lcom/fasterxml/jackson/databind/SerializationConfig;Lcom/fasterxml/jackson/databind/JavaType;Lcom/fasterxml/jackson/databind/BeanDescription;)Lcom/fasterxml/jackson/databind/JsonSerializer; +} + +public final class arrow/integrations/jackson/module/IorDeserializerResolver : com/fasterxml/jackson/databind/deser/Deserializers$Base { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun findBeanDeserializer (Lcom/fasterxml/jackson/databind/JavaType;Lcom/fasterxml/jackson/databind/DeserializationConfig;Lcom/fasterxml/jackson/databind/BeanDescription;)Lcom/fasterxml/jackson/databind/JsonDeserializer; +} + +public final class arrow/integrations/jackson/module/IorModule : com/fasterxml/jackson/databind/module/SimpleModule { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun setupModule (Lcom/fasterxml/jackson/databind/Module$SetupContext;)V +} + +public final class arrow/integrations/jackson/module/IorModuleConfig { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/lang/String; + public final fun copy (Ljava/lang/String;Ljava/lang/String;)Larrow/integrations/jackson/module/IorModuleConfig; + public static synthetic fun copy$default (Larrow/integrations/jackson/module/IorModuleConfig;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Larrow/integrations/jackson/module/IorModuleConfig; + public fun equals (Ljava/lang/Object;)Z + public final fun getLeftFieldName ()Ljava/lang/String; + public final fun getRightFieldName ()Ljava/lang/String; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class arrow/integrations/jackson/module/IorSerializerResolver : com/fasterxml/jackson/databind/ser/Serializers$Base { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun findSerializer (Lcom/fasterxml/jackson/databind/SerializationConfig;Lcom/fasterxml/jackson/databind/JavaType;Lcom/fasterxml/jackson/databind/BeanDescription;)Lcom/fasterxml/jackson/databind/JsonSerializer; +} + +public final class arrow/integrations/jackson/module/NonEmptyListDeserializerResolver : com/fasterxml/jackson/databind/deser/Deserializers$Base { + public static final field INSTANCE Larrow/integrations/jackson/module/NonEmptyListDeserializerResolver; + public fun findCollectionDeserializer (Lcom/fasterxml/jackson/databind/type/CollectionType;Lcom/fasterxml/jackson/databind/DeserializationConfig;Lcom/fasterxml/jackson/databind/BeanDescription;Lcom/fasterxml/jackson/databind/jsontype/TypeDeserializer;Lcom/fasterxml/jackson/databind/JsonDeserializer;)Lcom/fasterxml/jackson/databind/JsonDeserializer; +} + +public final class arrow/integrations/jackson/module/NonEmptyListModule : com/fasterxml/jackson/databind/module/SimpleModule { + public static final field INSTANCE Larrow/integrations/jackson/module/NonEmptyListModule; + public fun setupModule (Lcom/fasterxml/jackson/databind/Module$SetupContext;)V +} + +public final class arrow/integrations/jackson/module/NonEmptyListSerializationConverter : com/fasterxml/jackson/databind/util/StdConverter { + public static final field INSTANCE Larrow/integrations/jackson/module/NonEmptyListSerializationConverter; + public fun convert (Larrow/core/NonEmptyList;)Ljava/util/List; + public synthetic fun convert (Ljava/lang/Object;)Ljava/lang/Object; +} + +public final class arrow/integrations/jackson/module/OptionDeserializer : com/fasterxml/jackson/databind/JsonDeserializer, com/fasterxml/jackson/databind/deser/ContextualDeserializer { + public fun ()V + public fun createContextual (Lcom/fasterxml/jackson/databind/DeserializationContext;Lcom/fasterxml/jackson/databind/BeanProperty;)Lcom/fasterxml/jackson/databind/JsonDeserializer; + public fun deserialize (Lcom/fasterxml/jackson/core/JsonParser;Lcom/fasterxml/jackson/databind/DeserializationContext;)Larrow/core/Option; + public synthetic fun deserialize (Lcom/fasterxml/jackson/core/JsonParser;Lcom/fasterxml/jackson/databind/DeserializationContext;)Ljava/lang/Object; + public fun getEmptyAccessPattern ()Lcom/fasterxml/jackson/databind/util/AccessPattern; + public fun getEmptyValue (Lcom/fasterxml/jackson/databind/DeserializationContext;)Larrow/core/Option; + public synthetic fun getEmptyValue (Lcom/fasterxml/jackson/databind/DeserializationContext;)Ljava/lang/Object; + public fun getNullAccessPattern ()Lcom/fasterxml/jackson/databind/util/AccessPattern; + public fun getNullValue (Lcom/fasterxml/jackson/databind/DeserializationContext;)Larrow/core/Option; + public synthetic fun getNullValue (Lcom/fasterxml/jackson/databind/DeserializationContext;)Ljava/lang/Object; +} + +public final class arrow/integrations/jackson/module/OptionModule : com/fasterxml/jackson/databind/module/SimpleModule { + public static final field INSTANCE Larrow/integrations/jackson/module/OptionModule; + public fun setupModule (Lcom/fasterxml/jackson/databind/Module$SetupContext;)V +} + +public final class arrow/integrations/jackson/module/OptionSerializer : com/fasterxml/jackson/databind/ser/std/ReferenceTypeSerializer { + public fun (Larrow/integrations/jackson/module/OptionSerializer;Lcom/fasterxml/jackson/databind/BeanProperty;Lcom/fasterxml/jackson/databind/jsontype/TypeSerializer;Lcom/fasterxml/jackson/databind/JsonSerializer;Lcom/fasterxml/jackson/databind/util/NameTransformer;Ljava/lang/Object;Z)V + public fun (Lcom/fasterxml/jackson/databind/type/ReferenceType;ZLcom/fasterxml/jackson/databind/jsontype/TypeSerializer;Lcom/fasterxml/jackson/databind/JsonSerializer;)V + public synthetic fun _getReferenced (Ljava/lang/Object;)Ljava/lang/Object; + public synthetic fun _getReferencedIfPresent (Ljava/lang/Object;)Ljava/lang/Object; + public synthetic fun _isValuePresent (Ljava/lang/Object;)Z + public fun withContentInclusion (Ljava/lang/Object;Z)Lcom/fasterxml/jackson/databind/ser/std/ReferenceTypeSerializer; +} + +public final class arrow/integrations/jackson/module/OptionSerializerResolver : com/fasterxml/jackson/databind/ser/Serializers$Base { + public static final field INSTANCE Larrow/integrations/jackson/module/OptionSerializerResolver; + public fun findReferenceSerializer (Lcom/fasterxml/jackson/databind/SerializationConfig;Lcom/fasterxml/jackson/databind/type/ReferenceType;Lcom/fasterxml/jackson/databind/BeanDescription;Lcom/fasterxml/jackson/databind/jsontype/TypeSerializer;Lcom/fasterxml/jackson/databind/JsonSerializer;)Lcom/fasterxml/jackson/databind/JsonSerializer; +} + +public final class arrow/integrations/jackson/module/OptionTypeModifier : com/fasterxml/jackson/databind/type/TypeModifier { + public static final field INSTANCE Larrow/integrations/jackson/module/OptionTypeModifier; + public fun modifyType (Lcom/fasterxml/jackson/databind/JavaType;Ljava/lang/reflect/Type;Lcom/fasterxml/jackson/databind/type/TypeBindings;Lcom/fasterxml/jackson/databind/type/TypeFactory;)Lcom/fasterxml/jackson/databind/JavaType; +} + +public final class arrow/integrations/jackson/module/ValidatedDeserializerResolver : com/fasterxml/jackson/databind/deser/Deserializers$Base { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun findBeanDeserializer (Lcom/fasterxml/jackson/databind/JavaType;Lcom/fasterxml/jackson/databind/DeserializationConfig;Lcom/fasterxml/jackson/databind/BeanDescription;)Lcom/fasterxml/jackson/databind/JsonDeserializer; +} + +public final class arrow/integrations/jackson/module/ValidatedModule : com/fasterxml/jackson/databind/module/SimpleModule { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun setupModule (Lcom/fasterxml/jackson/databind/Module$SetupContext;)V +} + +public final class arrow/integrations/jackson/module/ValidatedModuleConfig { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/lang/String; + public final fun copy (Ljava/lang/String;Ljava/lang/String;)Larrow/integrations/jackson/module/ValidatedModuleConfig; + public static synthetic fun copy$default (Larrow/integrations/jackson/module/ValidatedModuleConfig;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Larrow/integrations/jackson/module/ValidatedModuleConfig; + public fun equals (Ljava/lang/Object;)Z + public final fun getInvalidFieldName ()Ljava/lang/String; + public final fun getValidFieldName ()Ljava/lang/String; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class arrow/integrations/jackson/module/ValidatedSerializerResolver : com/fasterxml/jackson/databind/ser/Serializers$Base { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun findSerializer (Lcom/fasterxml/jackson/databind/SerializationConfig;Lcom/fasterxml/jackson/databind/JavaType;Lcom/fasterxml/jackson/databind/BeanDescription;)Lcom/fasterxml/jackson/databind/JsonSerializer; +} + +public final class arrow/integrations/jackson/module/internal/ElementDeserializer { + public static final field Companion Larrow/integrations/jackson/module/internal/ElementDeserializer$Companion; + public fun (Larrow/core/Option;Larrow/core/Option;)V + public final fun component1 ()Larrow/core/Option; + public final fun component2 ()Larrow/core/Option; + public final fun copy (Larrow/core/Option;Larrow/core/Option;)Larrow/integrations/jackson/module/internal/ElementDeserializer; + public static synthetic fun copy$default (Larrow/integrations/jackson/module/internal/ElementDeserializer;Larrow/core/Option;Larrow/core/Option;ILjava/lang/Object;)Larrow/integrations/jackson/module/internal/ElementDeserializer; + public final fun deserialize (Lcom/fasterxml/jackson/databind/JavaType;Lcom/fasterxml/jackson/core/JsonToken;Lcom/fasterxml/jackson/core/JsonParser;Lcom/fasterxml/jackson/databind/DeserializationContext;)Ljava/lang/Object; + public fun equals (Ljava/lang/Object;)Z + public final fun getDeserializer ()Larrow/core/Option; + public final fun getTypeDeserializer ()Larrow/core/Option; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class arrow/integrations/jackson/module/internal/ElementDeserializer$Companion { + public final fun resolve (Lcom/fasterxml/jackson/databind/JavaType;Lcom/fasterxml/jackson/databind/DeserializationContext;Lcom/fasterxml/jackson/databind/BeanProperty;)Larrow/integrations/jackson/module/internal/ElementDeserializer; +} + +public final class arrow/integrations/jackson/module/internal/ProductTypeDeserializer : com/fasterxml/jackson/databind/deser/std/StdDeserializer, com/fasterxml/jackson/databind/deser/ContextualDeserializer { + public fun (Ljava/lang/Class;Lcom/fasterxml/jackson/databind/JavaType;Ljava/util/List;Lkotlin/jvm/functions/Function1;)V + public fun createContextual (Lcom/fasterxml/jackson/databind/DeserializationContext;Lcom/fasterxml/jackson/databind/BeanProperty;)Lcom/fasterxml/jackson/databind/JsonDeserializer; + public fun deserialize (Lcom/fasterxml/jackson/core/JsonParser;Lcom/fasterxml/jackson/databind/DeserializationContext;)Ljava/lang/Object; +} + +public final class arrow/integrations/jackson/module/internal/ProductTypeDeserializer$InjectField { + public fun (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V + public final fun getFieldName ()Ljava/lang/String; + public final fun getPoint ()Lkotlin/jvm/functions/Function1; +} + +public final class arrow/integrations/jackson/module/internal/ProductTypeSerializer : com/fasterxml/jackson/databind/ser/std/StdSerializer { + public fun (Ljava/lang/Class;Ljava/util/List;)V + public fun serialize (Ljava/lang/Object;Lcom/fasterxml/jackson/core/JsonGenerator;Lcom/fasterxml/jackson/databind/SerializerProvider;)V +} + +public final class arrow/integrations/jackson/module/internal/ProductTypeSerializer$ProjectField { + public fun (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V + public final fun getFieldName ()Ljava/lang/String; + public final fun getGetOption ()Lkotlin/jvm/functions/Function1; +} + +public final class arrow/integrations/jackson/module/internal/UnionTypeDeserializer : com/fasterxml/jackson/databind/deser/std/StdDeserializer, com/fasterxml/jackson/databind/deser/ContextualDeserializer { + public fun (Ljava/lang/Class;Lcom/fasterxml/jackson/databind/JavaType;Ljava/util/List;)V + public fun createContextual (Lcom/fasterxml/jackson/databind/DeserializationContext;Lcom/fasterxml/jackson/databind/BeanProperty;)Lcom/fasterxml/jackson/databind/JsonDeserializer; + public fun deserialize (Lcom/fasterxml/jackson/core/JsonParser;Lcom/fasterxml/jackson/databind/DeserializationContext;)Ljava/lang/Object; +} + +public final class arrow/integrations/jackson/module/internal/UnionTypeDeserializer$InjectField { + public fun (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V + public final fun getFieldName ()Ljava/lang/String; + public final fun getPoint ()Lkotlin/jvm/functions/Function1; +} + +public final class arrow/integrations/jackson/module/internal/UnionTypeSerializer : com/fasterxml/jackson/databind/ser/std/StdSerializer { + public fun (Ljava/lang/Class;Ljava/util/List;)V + public fun serialize (Ljava/lang/Object;Lcom/fasterxml/jackson/core/JsonGenerator;Lcom/fasterxml/jackson/databind/SerializerProvider;)V +} + +public final class arrow/integrations/jackson/module/internal/UnionTypeSerializer$ProjectField { + public fun (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V + public final fun getFieldName ()Ljava/lang/String; + public final fun getGetOption ()Lkotlin/jvm/functions/Function1; +} + diff --git a/arrow-integrations-jackson-module/build.gradle b/arrow-integrations-jackson-module/build.gradle deleted file mode 100644 index a24b65a..0000000 --- a/arrow-integrations-jackson-module/build.gradle +++ /dev/null @@ -1,17 +0,0 @@ -plugins { - id "org.jetbrains.kotlin.jvm" - id "org.jlleitschuh.gradle.ktlint" -} - -apply from: "$SUB_PROJECT" -// apply from: "$DOC_CREATION" -apply from: "$PUBLICATION" -// apply from: "$ANIMALSNIFFER" - -dependencies { - compile "io.arrow-kt:arrow-core:$ARROW_VERSION" - compile "com.fasterxml.jackson.module:jackson-module-kotlin:$JACKSON_MODULE_KOTLIN_VERSION" - testCompile "io.arrow-kt:arrow-core-test:$ARROW_VERSION" - testImplementation "io.kotest:kotest-property:$KOTEST_VERSION" - testImplementation "io.kotest:kotest-runner-junit5:$KOTEST_VERSION" -} diff --git a/arrow-integrations-jackson-module/build.gradle.kts b/arrow-integrations-jackson-module/build.gradle.kts new file mode 100644 index 0000000..3dd6a83 --- /dev/null +++ b/arrow-integrations-jackson-module/build.gradle.kts @@ -0,0 +1,24 @@ +@Suppress("DSL_SCOPE_VIOLATION") +plugins { + id(libs.plugins.kotlin.jvm.get().pluginId) + alias(libs.plugins.arrowGradleConfig.kotlin) + alias(libs.plugins.arrowGradleConfig.publish) + alias(libs.plugins.arrowGradleConfig.versioning) + alias(libs.plugins.animalsniffer) + `java-library` +} + +animalsniffer { + sourceSets = sourceSets.find { it.name == "main" }?.let(::listOf).orEmpty() // Ignore tests + ignore = listOf("java.lang.*") +} + +dependencies { + compileOnly(libs.animalsniffer.annotation) + signature("net.sf.androidscents.signature:android-api-level-21:5.0.1_r2@signature") + implementation(libs.arrowCore) + implementation(libs.jacksonModuleKotlin) + testImplementation(libs.arrowCoreTest) + testImplementation(libs.kotest.property) + testImplementation(libs.kotest.runnerJUnit5) +} diff --git a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/ArrowModule.kt b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/ArrowModule.kt index 253ab74..d31961c 100644 --- a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/ArrowModule.kt +++ b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/ArrowModule.kt @@ -2,18 +2,21 @@ package arrow.integrations.jackson.module import com.fasterxml.jackson.databind.ObjectMapper -fun ObjectMapper.registerArrowModule( +public fun ObjectMapper.registerArrowModule( eitherModuleConfig: EitherModuleConfig = EitherModuleConfig("left", "right"), validatedModuleConfig: ValidatedModuleConfig = ValidatedModuleConfig("invalid", "valid"), iorModuleConfig: IorModuleConfig = IorModuleConfig("left", "right") -): ObjectMapper = registerModules( - NonEmptyListModule, - OptionModule, - EitherModule(eitherModuleConfig.leftFieldName, eitherModuleConfig.rightFieldName), - ValidatedModule(validatedModuleConfig.invalidFieldName, validatedModuleConfig.validFieldName), - IorModule(iorModuleConfig.leftFieldName, iorModuleConfig.rightFieldName) -) +): ObjectMapper = + registerModules( + NonEmptyListModule, + OptionModule, + EitherModule(eitherModuleConfig.leftFieldName, eitherModuleConfig.rightFieldName), + ValidatedModule(validatedModuleConfig.invalidFieldName, validatedModuleConfig.validFieldName), + IorModule(iorModuleConfig.leftFieldName, iorModuleConfig.rightFieldName) + ) -data class EitherModuleConfig(val leftFieldName: String, val rightFieldName: String) -data class ValidatedModuleConfig(val invalidFieldName: String, val validFieldName: String) -data class IorModuleConfig(val leftFieldName: String, val rightFieldName: String) +public data class EitherModuleConfig(val leftFieldName: String, val rightFieldName: String) + +public data class ValidatedModuleConfig(val invalidFieldName: String, val validFieldName: String) + +public data class IorModuleConfig(val leftFieldName: String, val rightFieldName: String) diff --git a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/EitherModule.kt b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/EitherModule.kt index ba1e130..5c56c19 100644 --- a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/EitherModule.kt +++ b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/EitherModule.kt @@ -3,8 +3,8 @@ package arrow.integrations.jackson.module import arrow.core.Either import arrow.core.left import arrow.core.right -import arrow.integrations.jackson.module.internal.UnionTypeSerializer import arrow.integrations.jackson.module.internal.UnionTypeDeserializer +import arrow.integrations.jackson.module.internal.UnionTypeSerializer import com.fasterxml.jackson.core.json.PackageVersion import com.fasterxml.jackson.databind.BeanDescription import com.fasterxml.jackson.databind.DeserializationConfig @@ -16,10 +16,8 @@ import com.fasterxml.jackson.databind.deser.Deserializers import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.databind.ser.Serializers -class EitherModule( - private val leftFieldName: String, - private val rightFieldName: String -) : SimpleModule(EitherModule::class.java.canonicalName, PackageVersion.VERSION) { +public class EitherModule(private val leftFieldName: String, private val rightFieldName: String) : + SimpleModule(EitherModule::class.java.canonicalName, PackageVersion.VERSION) { override fun setupModule(context: SetupContext) { super.setupModule(context) context.addDeserializers(EitherDeserializerResolver(leftFieldName, rightFieldName)) @@ -27,26 +25,29 @@ class EitherModule( } } -class EitherSerializerResolver(leftFieldName: String, rightFieldName: String) : Serializers.Base() { - private val serializer = UnionTypeSerializer( - Either::class.java, - listOf( - UnionTypeSerializer.ProjectField(leftFieldName) { either -> either.swap().orNone() }, - UnionTypeSerializer.ProjectField(rightFieldName) { either -> either.orNone() } - ), - ) +public class EitherSerializerResolver(leftFieldName: String, rightFieldName: String) : + Serializers.Base() { + private val serializer = + UnionTypeSerializer( + Either::class.java, + listOf( + UnionTypeSerializer.ProjectField(leftFieldName) { either -> either.swap().orNone() }, + UnionTypeSerializer.ProjectField(rightFieldName) { either -> either.orNone() } + ), + ) override fun findSerializer( config: SerializationConfig, javaType: JavaType, beanDesc: BeanDescription? - ): JsonSerializer<*>? = when { - Either::class.java.isAssignableFrom(javaType.rawClass) -> serializer - else -> null - } + ): JsonSerializer<*>? = + when { + Either::class.java.isAssignableFrom(javaType.rawClass) -> serializer + else -> null + } } -class EitherDeserializerResolver( +public class EitherDeserializerResolver( private val leftFieldName: String, private val rightFieldName: String ) : Deserializers.Base() { @@ -54,15 +55,17 @@ class EitherDeserializerResolver( type: JavaType, config: DeserializationConfig, beanDesc: BeanDescription? - ): JsonDeserializer<*>? = when { - Either::class.java.isAssignableFrom(type.rawClass) -> UnionTypeDeserializer( - Either::class.java, - type, - listOf( - UnionTypeDeserializer.InjectField(leftFieldName) { leftValue -> leftValue.left() }, - UnionTypeDeserializer.InjectField(rightFieldName) { rightValue -> rightValue.right() } - ) - ) - else -> null - } + ): JsonDeserializer<*>? = + when { + Either::class.java.isAssignableFrom(type.rawClass) -> + UnionTypeDeserializer( + Either::class.java, + type, + listOf( + UnionTypeDeserializer.InjectField(leftFieldName) { leftValue -> leftValue.left() }, + UnionTypeDeserializer.InjectField(rightFieldName) { rightValue -> rightValue.right() } + ) + ) + else -> null + } } diff --git a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/IorModule.kt b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/IorModule.kt index 9499ae4..2b22e08 100644 --- a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/IorModule.kt +++ b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/IorModule.kt @@ -20,10 +20,8 @@ import com.fasterxml.jackson.databind.deser.Deserializers import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.databind.ser.Serializers -class IorModule( - private val leftFieldName: String, - private val rightFieldName: String -) : SimpleModule(IorModule::class.java.canonicalName, PackageVersion.VERSION) { +public class IorModule(private val leftFieldName: String, private val rightFieldName: String) : + SimpleModule(IorModule::class.java.canonicalName, PackageVersion.VERSION) { override fun setupModule(context: SetupContext) { super.setupModule(context) context.addDeserializers(IorDeserializerResolver(leftFieldName, rightFieldName)) @@ -31,26 +29,33 @@ class IorModule( } } -class IorSerializerResolver(leftFieldName: String, rightFieldName: String) : Serializers.Base() { - private val serializer = ProductTypeSerializer( - Ior::class.java, - listOf( - ProductTypeSerializer.ProjectField(leftFieldName) { ior -> ior.fold({ it.some() }, { none() }, { l, _ -> l.some() }) }, - ProductTypeSerializer.ProjectField(rightFieldName) { ior -> ior.fold({ none() }, { it.some() }, { _, r -> r.some() }) }, +public class IorSerializerResolver(leftFieldName: String, rightFieldName: String) : + Serializers.Base() { + private val serializer = + ProductTypeSerializer( + Ior::class.java, + listOf( + ProductTypeSerializer.ProjectField(leftFieldName) { ior -> + ior.fold({ it.some() }, { none() }, { l, _ -> l.some() }) + }, + ProductTypeSerializer.ProjectField(rightFieldName) { ior -> + ior.fold({ none() }, { it.some() }, { _, r -> r.some() }) + }, + ) ) - ) override fun findSerializer( config: SerializationConfig, type: JavaType, beanDesc: BeanDescription? - ): JsonSerializer<*>? = when { - Ior::class.java.isAssignableFrom(type.rawClass) -> serializer - else -> null - } + ): JsonSerializer<*>? = + when { + Ior::class.java.isAssignableFrom(type.rawClass) -> serializer + else -> null + } } -class IorDeserializerResolver( +public class IorDeserializerResolver( private val leftFieldName: String, private val rightFieldName: String ) : Deserializers.Base() { @@ -59,24 +64,31 @@ class IorDeserializerResolver( javaType: JavaType, config: DeserializationConfig, beanDesc: BeanDescription? - ): JsonDeserializer<*>? = when { - Ior::class.java.isAssignableFrom(javaType.rawClass) -> ProductTypeDeserializer( - Ior::class.java, - javaType, - listOf( - ProductTypeDeserializer.InjectField(leftFieldName) { firstValue -> firstValue.leftIor() }, - ProductTypeDeserializer.InjectField(rightFieldName) { secondValue -> secondValue.rightIor() }, - ) - ) { iors -> - // this reduce is safe because an Ior will always have either a left or a right - iors.reduce { first, second -> - first.combine(Semigroup.anyNonNull(), Semigroup.anyNonNull(), second) - } + ): JsonDeserializer<*>? = + when { + Ior::class.java.isAssignableFrom(javaType.rawClass) -> + ProductTypeDeserializer( + Ior::class.java, + javaType, + listOf( + ProductTypeDeserializer.InjectField(leftFieldName) { firstValue -> + firstValue.leftIor() + }, + ProductTypeDeserializer.InjectField(rightFieldName) { secondValue -> + secondValue.rightIor() + }, + ) + ) { iors -> + // this reduce is safe because an Ior will always have either a left or a right + iors.reduce { first, second -> + first.combine(Semigroup.anyNonNull(), Semigroup.anyNonNull(), second) + } + } + else -> null } - else -> null - } - private fun Semigroup.Companion.anyNonNull(): Semigroup = object : Semigroup { - override fun Any?.combine(b: Any?): Any? = b ?: this - } + private fun Semigroup.Companion.anyNonNull(): Semigroup = + object : Semigroup { + override fun Any?.combine(b: Any?): Any? = b ?: this + } } diff --git a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/NonEmptyListModule.kt b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/NonEmptyListModule.kt index f87e498..eebc46f 100644 --- a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/NonEmptyListModule.kt +++ b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/NonEmptyListModule.kt @@ -16,7 +16,8 @@ import com.fasterxml.jackson.databind.type.CollectionType import com.fasterxml.jackson.databind.type.TypeFactory import com.fasterxml.jackson.databind.util.StdConverter -object NonEmptyListModule : SimpleModule(NonEmptyListModule::class.java.canonicalName, PackageVersion.VERSION) { +public object NonEmptyListModule : + SimpleModule(NonEmptyListModule::class.java.canonicalName, PackageVersion.VERSION) { init { addSerializer( NonEmptyList::class.java, @@ -30,7 +31,7 @@ object NonEmptyListModule : SimpleModule(NonEmptyListModule::class.java.canonica } } -object NonEmptyListSerializationConverter : StdConverter, List<*>>() { +public object NonEmptyListSerializationConverter : StdConverter, List<*>>() { override fun convert(value: NonEmptyList<*>?): List<*>? = value?.all.orEmpty() } @@ -38,7 +39,11 @@ private class NonEmptyListDeserializationConverter(private val elementType: Java StdConverter, NonEmptyList?>() { override fun convert(value: List<*>?): NonEmptyList<*>? = - value?.let { NonEmptyList.fromList(it).getOrElse { throw IllegalArgumentException("NonEmptyList cannot be empty") } } + value?.let { + NonEmptyList.fromList(it).getOrElse { + throw IllegalArgumentException("NonEmptyList cannot be empty") + } + } override fun getInputType(typeFactory: TypeFactory): JavaType = typeFactory.constructCollectionType(List::class.java, elementType) @@ -47,7 +52,7 @@ private class NonEmptyListDeserializationConverter(private val elementType: Java typeFactory.constructCollectionLikeType(NonEmptyList::class.java, elementType) } -object NonEmptyListDeserializerResolver : Deserializers.Base() { +public object NonEmptyListDeserializerResolver : Deserializers.Base() { override fun findCollectionDeserializer( type: CollectionType, @@ -57,7 +62,9 @@ object NonEmptyListDeserializerResolver : Deserializers.Base() { elementDeserializer: JsonDeserializer<*>? ): JsonDeserializer>? = if (NonEmptyList::class.java.isAssignableFrom(type.rawClass)) { - StdDelegatingDeserializer>(NonEmptyListDeserializationConverter(type.bindings.getBoundType(0))) + StdDelegatingDeserializer>( + NonEmptyListDeserializationConverter(type.bindings.getBoundType(0)) + ) } else { null } diff --git a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/OptionModule.kt b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/OptionModule.kt index d8f557b..65bedf6 100644 --- a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/OptionModule.kt +++ b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/OptionModule.kt @@ -27,7 +27,8 @@ import com.fasterxml.jackson.databind.util.AccessPattern import com.fasterxml.jackson.databind.util.NameTransformer import java.lang.reflect.Type -object OptionModule : SimpleModule(OptionModule::class.java.canonicalName, PackageVersion.VERSION) { +public object OptionModule : + SimpleModule(OptionModule::class.java.canonicalName, PackageVersion.VERSION) { init { addDeserializer(Option::class.java, OptionDeserializer()) @@ -40,7 +41,7 @@ object OptionModule : SimpleModule(OptionModule::class.java.canonicalName, Packa } } -object OptionSerializerResolver : Serializers.Base() { +public object OptionSerializerResolver : Serializers.Base() { override fun findReferenceSerializer( config: SerializationConfig, type: ReferenceType, @@ -49,26 +50,38 @@ object OptionSerializerResolver : Serializers.Base() { contentValueSerializer: JsonSerializer? ): JsonSerializer<*>? = if (Option::class.java.isAssignableFrom(type.rawClass)) { - val staticTyping = (contentTypeSerializer == null && config.isEnabled(MapperFeature.USE_STATIC_TYPING)) + val staticTyping = + (contentTypeSerializer == null && config.isEnabled(MapperFeature.USE_STATIC_TYPING)) OptionSerializer(type, staticTyping, contentTypeSerializer, contentValueSerializer) } else { null } } -object OptionTypeModifier : TypeModifier() { - override fun modifyType(type: JavaType, jdkType: Type, context: TypeBindings?, typeFactory: TypeFactory?): JavaType = when { - type.isReferenceType || type.isContainerType -> type - type.rawClass == Option::class.java -> ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0)) - else -> type - } +public object OptionTypeModifier : TypeModifier() { + override fun modifyType( + type: JavaType, + jdkType: Type, + context: TypeBindings?, + typeFactory: TypeFactory? + ): JavaType = + when { + type.isReferenceType || type.isContainerType -> type + type.rawClass == Option::class.java -> + ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0)) + else -> type + } } -class OptionSerializer : ReferenceTypeSerializer> { - constructor(fullType: ReferenceType, staticTyping: Boolean, typeSerializer: TypeSerializer?, jsonSerializer: JsonSerializer?) : - super(fullType, staticTyping, typeSerializer, jsonSerializer) +public class OptionSerializer : ReferenceTypeSerializer> { + public constructor( + fullType: ReferenceType, + staticTyping: Boolean, + typeSerializer: TypeSerializer?, + jsonSerializer: JsonSerializer? + ) : super(fullType, staticTyping, typeSerializer, jsonSerializer) - constructor( + public constructor( base: OptionSerializer, property: BeanProperty?, typeSerializer: TypeSerializer?, @@ -78,29 +91,46 @@ class OptionSerializer : ReferenceTypeSerializer> { suppressNulls: Boolean ) : super(base, property, typeSerializer, valueSer, unwrapper, suppressableValue, suppressNulls) - override fun withContentInclusion(suppressableValue: Any?, suppressNulls: Boolean): ReferenceTypeSerializer> = - OptionSerializer(this, _property, _valueTypeSerializer, _valueSerializer, _unwrapper, suppressableValue, suppressNulls) + override fun withContentInclusion( + suppressableValue: Any?, + suppressNulls: Boolean + ): ReferenceTypeSerializer> = + OptionSerializer( + this, + _property, + _valueTypeSerializer, + _valueSerializer, + _unwrapper, + suppressableValue, + suppressNulls + ) override fun _isValuePresent(value: Option<*>): Boolean = value.isDefined() override fun _getReferenced(value: Option<*>): Any? = value.orNull() override fun _getReferencedIfPresent(value: Option<*>): Any? = value.orNull() - override fun withResolved(prop: BeanProperty?, vts: TypeSerializer?, valueSer: JsonSerializer<*>?, unwrapper: NameTransformer?): - ReferenceTypeSerializer> = OptionSerializer(this, prop, vts, valueSer, unwrapper, _suppressableValue, _suppressNulls) + override fun withResolved( + prop: BeanProperty?, + vts: TypeSerializer?, + valueSer: JsonSerializer<*>?, + unwrapper: NameTransformer? + ): ReferenceTypeSerializer> = + OptionSerializer(this, prop, vts, valueSer, unwrapper, _suppressableValue, _suppressNulls) } -class OptionDeserializer : JsonDeserializer>(), ContextualDeserializer { +public class OptionDeserializer : JsonDeserializer>(), ContextualDeserializer { private lateinit var valueType: JavaType override fun deserialize(p: JsonParser?, ctxt: DeserializationContext): Option<*> = - Option.fromNullable(p).map { - ctxt.readValue(it, valueType) - } + Option.fromNullable(p).map { ctxt.readValue(it, valueType) } - override fun createContextual(ctxt: DeserializationContext, property: BeanProperty?): JsonDeserializer<*> { - val valueType = Option - .fromNullable(property) - .map { it.type.containedTypeOrUnknown(0) } - .or(Option.fromNullable(ctxt.contextualType?.containedTypeOrUnknown(0))) - .getOrElse { ctxt.constructType(Any::class.java) } + override fun createContextual( + ctxt: DeserializationContext, + property: BeanProperty? + ): JsonDeserializer<*> { + val valueType = + Option.fromNullable(property) + .map { it.type.containedTypeOrUnknown(0) } + .or(Option.fromNullable(ctxt.contextualType?.containedTypeOrUnknown(0))) + .getOrElse { ctxt.constructType(Any::class.java) } val deserializer = OptionDeserializer() deserializer.valueType = valueType diff --git a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/ValidatedModule.kt b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/ValidatedModule.kt index 4799179..67b6fa1 100644 --- a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/ValidatedModule.kt +++ b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/ValidatedModule.kt @@ -17,7 +17,7 @@ import com.fasterxml.jackson.databind.deser.Deserializers import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.databind.ser.Serializers -class ValidatedModule( +public class ValidatedModule( private val invalidFieldName: String, private val validFieldName: String ) : SimpleModule(ValidatedModule::class.java.canonicalName, PackageVersion.VERSION) { @@ -28,26 +28,31 @@ class ValidatedModule( } } -class ValidatedSerializerResolver(invalidFieldName: String, validFieldName: String) : Serializers.Base() { - private val serializer = UnionTypeSerializer( - Validated::class.java, - listOf( - UnionTypeSerializer.ProjectField(invalidFieldName) { validated -> validated.swap().orNone() }, - UnionTypeSerializer.ProjectField(validFieldName) { validated -> validated.orNone() }, +public class ValidatedSerializerResolver(invalidFieldName: String, validFieldName: String) : + Serializers.Base() { + private val serializer = + UnionTypeSerializer( + Validated::class.java, + listOf( + UnionTypeSerializer.ProjectField(invalidFieldName) { validated -> + validated.swap().orNone() + }, + UnionTypeSerializer.ProjectField(validFieldName) { validated -> validated.orNone() }, + ) ) - ) override fun findSerializer( config: SerializationConfig, type: JavaType, beanDesc: BeanDescription? - ): JsonSerializer<*>? = when { - Validated::class.java.isAssignableFrom(type.rawClass) -> serializer - else -> null - } + ): JsonSerializer<*>? = + when { + Validated::class.java.isAssignableFrom(type.rawClass) -> serializer + else -> null + } } -class ValidatedDeserializerResolver( +public class ValidatedDeserializerResolver( private val invalidFieldName: String, private val validFieldName: String ) : Deserializers.Base() { @@ -55,15 +60,19 @@ class ValidatedDeserializerResolver( type: JavaType, config: DeserializationConfig, beanDesc: BeanDescription? - ): JsonDeserializer<*>? = when { - Validated::class.java.isAssignableFrom(type.rawClass) -> UnionTypeDeserializer( - Validated::class.java, - type, - listOf( - UnionTypeDeserializer.InjectField(invalidFieldName) { invalidValue -> invalidValue.invalid() }, - UnionTypeDeserializer.InjectField(validFieldName) { validValue -> validValue.valid() }, - ) - ) - else -> null - } + ): JsonDeserializer<*>? = + when { + Validated::class.java.isAssignableFrom(type.rawClass) -> + UnionTypeDeserializer( + Validated::class.java, + type, + listOf( + UnionTypeDeserializer.InjectField(invalidFieldName) { invalidValue -> + invalidValue.invalid() + }, + UnionTypeDeserializer.InjectField(validFieldName) { validValue -> validValue.valid() }, + ) + ) + else -> null + } } diff --git a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ElementDeserializer.kt b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ElementDeserializer.kt index f024546..d8a70c2 100644 --- a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ElementDeserializer.kt +++ b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ElementDeserializer.kt @@ -11,40 +11,54 @@ import com.fasterxml.jackson.databind.JsonDeserializer import com.fasterxml.jackson.databind.deser.BeanDeserializerFactory import com.fasterxml.jackson.databind.jsontype.TypeDeserializer -data class ElementDeserializer( +public data class ElementDeserializer( val deserializer: Option>, val typeDeserializer: Option ) { - companion object { - fun resolve(containedType: JavaType, context: DeserializationContext, property: BeanProperty?) = + public companion object { + public fun resolve( + containedType: JavaType, + context: DeserializationContext, + property: BeanProperty? + ): ElementDeserializer = ElementDeserializer( deserializer = context.findContextualValueDeserializer(containedType, property).toOption(), - typeDeserializer = property.toOption().flatMap { prop -> - BeanDeserializerFactory.instance - .findPropertyTypeDeserializer(context.config, containedType, prop.member) - .toOption() - } + typeDeserializer = + property.toOption().flatMap { prop -> + BeanDeserializerFactory.instance + .findPropertyTypeDeserializer(context.config, containedType, prop.member) + .toOption() + } ) } - fun deserialize( + public fun deserialize( javaType: JavaType, token: JsonToken, parser: JsonParser, context: DeserializationContext - ): Any? = when (token) { - JsonToken.VALUE_NULL -> null - else -> deserializer.fold( - { context.handleUnexpectedToken(javaType.rawClass, token, parser, "no deserializer was found for given type") }, - { deserializer -> - typeDeserializer.fold( - { deserializer.deserialize(parser, context) }, // only deserializer found - { typeDeserializer -> - // both deserializer and type deserializer found - deserializer.deserializeWithType(parser, context, typeDeserializer) + ): Any? = + when (token) { + JsonToken.VALUE_NULL -> null + else -> + deserializer.fold( + { + context.handleUnexpectedToken( + javaType.rawClass, + token, + parser, + "no deserializer was found for given type" + ) + }, + { deserializer -> + typeDeserializer.fold( + { deserializer.deserialize(parser, context) }, // only deserializer found + { typeDeserializer -> + // both deserializer and type deserializer found + deserializer.deserializeWithType(parser, context, typeDeserializer) + } + ) } ) - } - ) - } + } } diff --git a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ProductTypeDeserializer.kt b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ProductTypeDeserializer.kt index da07272..d73a843 100644 --- a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ProductTypeDeserializer.kt +++ b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ProductTypeDeserializer.kt @@ -10,13 +10,13 @@ import com.fasterxml.jackson.databind.JsonDeserializer import com.fasterxml.jackson.databind.deser.ContextualDeserializer import com.fasterxml.jackson.databind.deser.std.StdDeserializer -class ProductTypeDeserializer( +public class ProductTypeDeserializer( private val clazz: Class, private val javaType: JavaType, private val fields: List>, private val fold: (List) -> T ) : StdDeserializer(clazz), ContextualDeserializer { - class InjectField(val fieldName: String, val point: (Any?) -> T) + public class InjectField(public val fieldName: String, public val point: (Any?) -> T) private val deserializers: MutableMap = mutableMapOf() @@ -25,36 +25,49 @@ class ProductTypeDeserializer( val introspectedFields: MutableSet = mutableSetOf() while (parser.nextToken() != JsonToken.END_OBJECT) { - fields.firstOrNone { parser.currentName == it.fieldName }.fold( - { - val validFields = fields.map { it.fieldName } - val message = "Cannot deserialize $javaType. Make sure json fields are valid: $validFields." - @Suppress("UNCHECKED_CAST") - ctxt.handleUnexpectedToken(clazz, parser.currentToken, parser, message) as T - }, - { injectField -> - if (introspectedFields.add(injectField.fieldName)) { - val elementDeserializer = requireNotNull(deserializers[injectField.fieldName]) { - "unexpected deserializer not found" + fields + .firstOrNone { parser.currentName == it.fieldName } + .fold( + { + val validFields = fields.map { it.fieldName } + val message = + "Cannot deserialize $javaType. Make sure json fields are valid: $validFields." + @Suppress("UNCHECKED_CAST") + ctxt.handleUnexpectedToken(clazz, parser.currentToken, parser, message) as T + }, + { injectField -> + if (introspectedFields.add(injectField.fieldName)) { + val elementDeserializer = + requireNotNull(deserializers[injectField.fieldName]) { + "unexpected deserializer not found" + } + val value = + elementDeserializer.deserialize(javaType, parser.nextToken(), parser, ctxt) + params.add(injectField.point(value)) + } else { + val message = + "Malformed Json: Field collision were detected for ${parser.currentName}" + ctxt.handleUnexpectedToken(clazz, parser.currentToken, parser, message) } - val value = elementDeserializer.deserialize(javaType, parser.nextToken(), parser, ctxt) - params.add(injectField.point(value)) - } else { - val message = "Malformed Json: Field collision were detected for ${parser.currentName}" - ctxt.handleUnexpectedToken(clazz, parser.currentToken, parser, message) } - } - ) + ) } return fold(params) } - override fun createContextual(ctxt: DeserializationContext, property: BeanProperty?): JsonDeserializer<*> = + override fun createContextual( + ctxt: DeserializationContext, + property: BeanProperty? + ): JsonDeserializer<*> = ProductTypeDeserializer(clazz, javaType, fields, fold).also { deserializer -> fields.forEachIndexed { index, field -> deserializer.deserializers[field.fieldName] = - ElementDeserializer.resolve(ctxt.contextualType.containedTypeOrUnknown(index), ctxt, property) + ElementDeserializer.resolve( + ctxt.contextualType.containedTypeOrUnknown(index), + ctxt, + property + ) } } } diff --git a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ProductTypeSerializer.kt b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ProductTypeSerializer.kt index 2bfd75c..55225ec 100644 --- a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ProductTypeSerializer.kt +++ b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/ProductTypeSerializer.kt @@ -5,8 +5,12 @@ import com.fasterxml.jackson.core.JsonGenerator import com.fasterxml.jackson.databind.SerializerProvider import com.fasterxml.jackson.databind.ser.std.StdSerializer -class ProductTypeSerializer(clazz: Class, private val fields: List>) : StdSerializer(clazz) { - class ProjectField(val fieldName: String, val getOption: (T) -> Option<*>) +public class ProductTypeSerializer(clazz: Class, private val fields: List>) : + StdSerializer(clazz) { + public class ProjectField( + public val fieldName: String, + public val getOption: (T) -> Option<*> + ) override fun serialize(value: T, gen: JsonGenerator, provider: SerializerProvider) { gen.writeStartObject() diff --git a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/UnionTypeDeserializer.kt b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/UnionTypeDeserializer.kt index 99067f2..15491ad 100644 --- a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/UnionTypeDeserializer.kt +++ b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/UnionTypeDeserializer.kt @@ -9,39 +9,50 @@ import com.fasterxml.jackson.databind.JsonDeserializer import com.fasterxml.jackson.databind.deser.ContextualDeserializer import com.fasterxml.jackson.databind.deser.std.StdDeserializer -class UnionTypeDeserializer( +public class UnionTypeDeserializer( private val clazz: Class, private val javaType: JavaType, private val fields: List>, ) : StdDeserializer(clazz), ContextualDeserializer { - class InjectField(val fieldName: String, val point: (Any?) -> T) + public class InjectField(public val fieldName: String, public val point: (Any?) -> T) private val deserializers: MutableMap = mutableMapOf() override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): T { parser.nextToken() - return fields.firstOrNone { parser.currentName == it.fieldName }.fold( - { - val validFields = fields.map { it.fieldName } - val message = "Cannot deserialize $javaType. Make sure json fields are valid: $validFields." - @Suppress("UNCHECKED_CAST") - ctxt.handleUnexpectedToken(clazz, parser.currentToken, parser, message) as T - }, - { injectField -> - val elementDeserializer = requireNotNull(deserializers[injectField.fieldName]) { - "unexpected deserializer not found" + return fields + .firstOrNone { parser.currentName == it.fieldName } + .fold( + { + val validFields = fields.map { it.fieldName } + val message = + "Cannot deserialize $javaType. Make sure json fields are valid: $validFields." + @Suppress("UNCHECKED_CAST") + ctxt.handleUnexpectedToken(clazz, parser.currentToken, parser, message) as T + }, + { injectField -> + val elementDeserializer = + requireNotNull(deserializers[injectField.fieldName]) { + "unexpected deserializer not found" + } + val value = elementDeserializer.deserialize(javaType, parser.nextToken(), parser, ctxt) + injectField.point(value) } - val value = elementDeserializer.deserialize(javaType, parser.nextToken(), parser, ctxt) - injectField.point(value) - } - ) + ) } - override fun createContextual(ctxt: DeserializationContext, property: BeanProperty?): JsonDeserializer<*> = + override fun createContextual( + ctxt: DeserializationContext, + property: BeanProperty? + ): JsonDeserializer<*> = UnionTypeDeserializer(clazz, javaType, fields).also { deserializer -> fields.forEachIndexed { index, field -> deserializer.deserializers[field.fieldName] = - ElementDeserializer.resolve(ctxt.contextualType.containedTypeOrUnknown(index), ctxt, property) + ElementDeserializer.resolve( + ctxt.contextualType.containedTypeOrUnknown(index), + ctxt, + property + ) } } } diff --git a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/UnionTypeSerializer.kt b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/UnionTypeSerializer.kt index c2e6ceb..590455d 100644 --- a/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/UnionTypeSerializer.kt +++ b/arrow-integrations-jackson-module/src/main/kotlin/arrow/integrations/jackson/module/internal/UnionTypeSerializer.kt @@ -5,18 +5,21 @@ import com.fasterxml.jackson.core.JsonGenerator import com.fasterxml.jackson.databind.SerializerProvider import com.fasterxml.jackson.databind.ser.std.StdSerializer -class UnionTypeSerializer(clazz: Class, private val fields: List>) : StdSerializer(clazz) { - class ProjectField(val fieldName: String, val getOption: (T) -> Option<*>) +public class UnionTypeSerializer(clazz: Class, private val fields: List>) : + StdSerializer(clazz) { + public class ProjectField( + public val fieldName: String, + public val getOption: (T) -> Option<*> + ) override fun serialize(value: T, gen: JsonGenerator, provider: SerializerProvider) { - val project = requireNotNull(fields.firstOrNull { it.getOption(value).isDefined() }) { - "unexpected failure when attempting projection during serialization" - } + val project = + requireNotNull(fields.firstOrNull { it.getOption(value).isDefined() }) { + "unexpected failure when attempting projection during serialization" + } gen.writeStartObject() - project.getOption(value).map { - provider.defaultSerializeField(project.fieldName, it, gen) - } + project.getOption(value).map { provider.defaultSerializeField(project.fieldName, it, gen) } gen.writeEndObject() } } diff --git a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/DataHelpers.kt b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/DataHelpers.kt index 956d525..a919e22 100644 --- a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/DataHelpers.kt +++ b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/DataHelpers.kt @@ -7,4 +7,5 @@ import io.kotest.property.arbitrary.string data class SomeObject(val someString: String, val someInt: Int) -fun Arb.Companion.someObject(): Arb = Arb.bind(Arb.string(), Arb.int()) { str, int -> SomeObject(str, int) } +fun Arb.Companion.someObject(): Arb = + Arb.bind(Arb.string(), Arb.int()) { str, int -> SomeObject(str, int) } diff --git a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/EitherModuleTest.kt b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/EitherModuleTest.kt index 1b994ef..ce62205 100644 --- a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/EitherModuleTest.kt +++ b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/EitherModuleTest.kt @@ -54,14 +54,14 @@ class EitherModuleTest : FunSpec() { test("should serialize with configurable left / right field name") { checkAll( - Arb.pair( - Arb.string(10, Codepoint.az()), - Arb.string(10, Codepoint.az()) - ).filter { it.first != it.second } + Arb.pair(Arb.string(10, Codepoint.az()), Arb.string(10, Codepoint.az())).filter { + it.first != it.second + } ) { (leftFieldName, rightFieldName) -> - val mapper = ObjectMapper() - .registerKotlinModule() - .registerArrowModule(EitherModuleConfig(leftFieldName, rightFieldName)) + val mapper = + ObjectMapper() + .registerKotlinModule() + .registerArrowModule(EitherModuleConfig(leftFieldName, rightFieldName)) mapper.writeValueAsString(5.left()) shouldBe """{"$leftFieldName":5}""" mapper.writeValueAsString("hello".right()) shouldBe """{"$rightFieldName":"hello"}""" @@ -71,14 +71,18 @@ class EitherModuleTest : FunSpec() { test("should round-trip with configurable left / right field name") { checkAll( Arb.pair( - Arb.string(10, Codepoint.az()), - Arb.string(10, Codepoint.az()), - ).filter { it.first != it.second }, + Arb.string(10, Codepoint.az()), + Arb.string(10, Codepoint.az()), + ) + .filter { it.first != it.second }, arbTestClass ) { (leftFieldName, rightFieldName), testClass -> - val mapper = ObjectMapper().registerKotlinModule().registerArrowModule( - eitherModuleConfig = EitherModuleConfig(leftFieldName, rightFieldName) - ) + val mapper = + ObjectMapper() + .registerKotlinModule() + .registerArrowModule( + eitherModuleConfig = EitherModuleConfig(leftFieldName, rightFieldName) + ) testClass.shouldRoundTrip(mapper) } @@ -115,23 +119,19 @@ class EitherModuleTest : FunSpec() { } } - private data class Foo(@get:JsonProperty("foo") val fooValue: Option, val otherValue: String) + private data class Foo( + @get:JsonProperty("foo") val fooValue: Option, + val otherValue: String + ) private data class Bar(val first: Int, val second: String, val third: Boolean) private data class TestClass(val either: Either) private val arbFoo: Arb = arbitrary { - Foo( - Arb.option(Arb.int()).bind(), - Arb.string().bind() - ) + Foo(Arb.option(Arb.int()).bind(), Arb.string().bind()) } private val arbBar: Arb = arbitrary { - Bar( - Arb.int().bind(), - Arb.string(0..100, Codepoint.alphanumeric()).bind(), - Arb.boolean().bind() - ) + Bar(Arb.int().bind(), Arb.string(0..100, Codepoint.alphanumeric()).bind(), Arb.boolean().bind()) } private val arbTestClass: Arb = arbitrary { diff --git a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/ExampleTest.kt b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/ExampleTest.kt index 6cf3891..ce247b1 100644 --- a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/ExampleTest.kt +++ b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/ExampleTest.kt @@ -16,34 +16,43 @@ import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe import java.net.URI -class ExampleTest : FunSpec({ - - data class Organization(val name: String, val address: Option, val websiteUrl: Option) - - data class ArrowUser( - val name: String, - val emails: NonEmptyList, - val organization: Option - ) - - val mapper = ObjectMapper() - .registerKotlinModule() - .registerArrowModule() - .setSerializationInclusion(JsonInclude.Include.NON_ABSENT) // will not serialize None as nulls - - val prettyPrinter = mapper.writerWithDefaultPrettyPrinter() - - test("example #1: data structure serialization") { - val arrowKt = Organization("arrow-kt", none(), URI("https://arrow-kt.io").some()) - val arrowUser = ArrowUser( - "John Doe", - nonEmptyListOf("john@email.com", "john.doe@email.com.au"), - arrowKt.some() +class ExampleTest : + FunSpec({ + data class Organization( + val name: String, + val address: Option, + val websiteUrl: Option ) - val jsonString = prettyPrinter.writeValueAsString(arrowUser) + data class ArrowUser( + val name: String, + val emails: NonEmptyList, + val organization: Option + ) - jsonString shouldBe """ + val mapper = + ObjectMapper() + .registerKotlinModule() + .registerArrowModule() + .setSerializationInclusion( + JsonInclude.Include.NON_ABSENT + ) // will not serialize None as nulls + + val prettyPrinter = mapper.writerWithDefaultPrettyPrinter() + + test("example #1: data structure serialization") { + val arrowKt = Organization("arrow-kt", none(), URI("https://arrow-kt.io").some()) + val arrowUser = + ArrowUser( + "John Doe", + nonEmptyListOf("john@email.com", "john.doe@email.com.au"), + arrowKt.some() + ) + + val jsonString = prettyPrinter.writeValueAsString(arrowUser) + + jsonString shouldBe + """ { "name" : "John Doe", "emails" : [ "john@email.com", "john.doe@email.com.au" ], @@ -54,12 +63,13 @@ class ExampleTest : FunSpec({ } """.trimIndent() - mapper.readValue(jsonString, ArrowUser::class.java) shouldBe arrowUser - } + mapper.readValue(jsonString, ArrowUser::class.java) shouldBe arrowUser + } - test("example #2: validated") { - val arrowKt = Organization("arrow-kt", none(), URI("https://arrow-kt.io").some()) - prettyPrinter.writeValueAsString(arrowKt.valid()) shouldBe """ + test("example #2: validated") { + val arrowKt = Organization("arrow-kt", none(), URI("https://arrow-kt.io").some()) + prettyPrinter.writeValueAsString(arrowKt.valid()) shouldBe + """ { "valid" : { "name" : "arrow-kt", @@ -67,26 +77,28 @@ class ExampleTest : FunSpec({ } } """.trimIndent() - } + } - test("example #3: either") { - data class Fruit(@get:JsonValue val name: String) + test("example #3: either") { + data class Fruit(@get:JsonValue val name: String) - val apricot = Fruit("apricot") - prettyPrinter.writeValueAsString(apricot.right()) shouldBe """ + val apricot = Fruit("apricot") + prettyPrinter.writeValueAsString(apricot.right()) shouldBe + """ { "right" : "apricot" } """.trimIndent() - } + } - test("example #4: ior") { - data class Fruit(@get:JsonValue val name: String) - data class Vegetable(val name: String, val kind: String) + test("example #4: ior") { + data class Fruit(@get:JsonValue val name: String) + data class Vegetable(val name: String, val kind: String) - val starfruit = Fruit("starfruit") - val spinach = Vegetable("spinach", "leafy greens") - prettyPrinter.writeValueAsString(Pair(starfruit, spinach).bothIor()) shouldBe """ + val starfruit = Fruit("starfruit") + val spinach = Vegetable("spinach", "leafy greens") + prettyPrinter.writeValueAsString(Pair(starfruit, spinach).bothIor()) shouldBe + """ { "left" : "starfruit", "right" : { @@ -95,21 +107,23 @@ class ExampleTest : FunSpec({ } } """.trimIndent() - } - - test("example #5: customizing field names") { - data class Fruit(@get:JsonValue val name: String) - data class Vegetable(val name: String, val kind: String) - - val customMapper = ObjectMapper() - .registerKotlinModule() - .registerArrowModule( - iorModuleConfig = IorModuleConfig("l", "r") - ) - - val starfruit = Fruit("starfruit") - val spinach = Vegetable("spinach", "leafy greens") - customMapper.writerWithDefaultPrettyPrinter().writeValueAsString(Pair(starfruit, spinach).bothIor()) shouldBe """ + } + + test("example #5: customizing field names") { + data class Fruit(@get:JsonValue val name: String) + data class Vegetable(val name: String, val kind: String) + + val customMapper = + ObjectMapper() + .registerKotlinModule() + .registerArrowModule(iorModuleConfig = IorModuleConfig("l", "r")) + + val starfruit = Fruit("starfruit") + val spinach = Vegetable("spinach", "leafy greens") + customMapper + .writerWithDefaultPrettyPrinter() + .writeValueAsString(Pair(starfruit, spinach).bothIor()) shouldBe + """ { "l" : "starfruit", "r" : { @@ -118,5 +132,5 @@ class ExampleTest : FunSpec({ } } """.trimIndent() - } -}) + } + }) diff --git a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/IorModuleTest.kt b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/IorModuleTest.kt index b17e901..76bb38a 100644 --- a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/IorModuleTest.kt +++ b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/IorModuleTest.kt @@ -45,25 +45,20 @@ class IorModuleTest : FunSpec() { test("should round-trip nested ior types") { checkAll( - Arb.ior( - Arb.ior(arbFoo, Arb.int()).orNull(), - Arb.ior(Arb.string(), arbBar.orNull()) - ) - ) { ior: Ior?, Ior> -> - ior.shouldRoundTrip(mapper) - } + Arb.ior(Arb.ior(arbFoo, Arb.int()).orNull(), Arb.ior(Arb.string(), arbBar.orNull())) + ) { ior: Ior?, Ior> -> ior.shouldRoundTrip(mapper) } } test("should serialize with configurable left / right field name") { checkAll( - Arb.pair( - Arb.string(10, Codepoint.az()), - Arb.string(10, Codepoint.az()) - ).filter { it.first != it.second } + Arb.pair(Arb.string(10, Codepoint.az()), Arb.string(10, Codepoint.az())).filter { + it.first != it.second + } ) { (leftFieldName, rightFieldName) -> - val mapper = ObjectMapper() - .registerKotlinModule() - .registerArrowModule(iorModuleConfig = IorModuleConfig(leftFieldName, rightFieldName)) + val mapper = + ObjectMapper() + .registerKotlinModule() + .registerArrowModule(iorModuleConfig = IorModuleConfig(leftFieldName, rightFieldName)) mapper.writeValueAsString(5.leftIor()) shouldBe """{"$leftFieldName":5}""" mapper.writeValueAsString("hello".rightIor()) shouldBe """{"$rightFieldName":"hello"}""" @@ -75,14 +70,18 @@ class IorModuleTest : FunSpec() { test("should round-trip with configurable left / right field name") { checkAll( Arb.pair( - Arb.string(10, Codepoint.az()), - Arb.string(10, Codepoint.az()), - ).filter { it.first != it.second }, + Arb.string(10, Codepoint.az()), + Arb.string(10, Codepoint.az()), + ) + .filter { it.first != it.second }, arbTestClass ) { (leftFieldName, rightFieldName), testClass -> - val mapper = ObjectMapper().registerKotlinModule().registerArrowModule( - eitherModuleConfig = EitherModuleConfig(leftFieldName, rightFieldName) - ) + val mapper = + ObjectMapper() + .registerKotlinModule() + .registerArrowModule( + eitherModuleConfig = EitherModuleConfig(leftFieldName, rightFieldName) + ) testClass.shouldRoundTrip(mapper) } @@ -90,7 +89,11 @@ class IorModuleTest : FunSpec() { } } - private enum class IorPolarity { Left, Both, Right } + private enum class IorPolarity { + Left, + Both, + Right + } private val arbTestClassJsonString = arbitrary { when (Arb.enum().bind()) { @@ -143,28 +146,22 @@ class IorModuleTest : FunSpec() { } } - private data class Foo(@get:JsonProperty("foo") val fooValue: Option, val otherValue: String) + private data class Foo( + @get:JsonProperty("foo") val fooValue: Option, + val otherValue: String + ) private data class Bar(val first: Int, val second: String, val third: Boolean) private data class TestClass(val ior: Ior) private val arbFoo: Arb = arbitrary { - Foo( - Arb.option(Arb.int()).bind(), - Arb.string().bind() - ) + Foo(Arb.option(Arb.int()).bind(), Arb.string().bind()) } private val arbBar: Arb = arbitrary { - Bar( - Arb.int().bind(), - Arb.string(0..100, Codepoint.alphanumeric()).bind(), - Arb.boolean().bind() - ) + Bar(Arb.int().bind(), Arb.string(0..100, Codepoint.alphanumeric()).bind(), Arb.boolean().bind()) } - private val arbTestClass: Arb = arbitrary { - TestClass(Arb.ior(arbFoo, arbBar).bind()) - } + private val arbTestClass: Arb = arbitrary { TestClass(Arb.ior(arbFoo, arbBar).bind()) } private val mapper = ObjectMapper().registerKotlinModule().registerArrowModule() } diff --git a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/NonEmptyListModuleTest.kt b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/NonEmptyListModuleTest.kt index e833143..974744e 100644 --- a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/NonEmptyListModuleTest.kt +++ b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/NonEmptyListModuleTest.kt @@ -18,7 +18,9 @@ class NonEmptyListModuleTest : UnitSpec() { init { "serializing NonEmptyList should be the same as serializing the underlying list" { - checkAll(Arb.nonEmptyList(Arb.choice(Arb.someObject(), Arb.int(), Arb.string(), Arb.boolean()))) { list -> + checkAll( + Arb.nonEmptyList(Arb.choice(Arb.someObject(), Arb.int(), Arb.string(), Arb.boolean())) + ) { list -> val actual = mapper.writeValueAsString(list) val expected = mapper.writeValueAsString(list.all) @@ -29,7 +31,9 @@ class NonEmptyListModuleTest : UnitSpec() { "serializing NonEmptyList and then deserialize it should be the same as before the deserialization" { checkAll( Arb.choice( - arbitrary { Arb.nonEmptyList(Arb.someObject()).bind() to jacksonTypeRef>() }, + arbitrary { + Arb.nonEmptyList(Arb.someObject()).bind() to jacksonTypeRef>() + }, arbitrary { Arb.nonEmptyList(Arb.int()).bind() to jacksonTypeRef>() }, arbitrary { Arb.nonEmptyList(Arb.string()).bind() to jacksonTypeRef>() }, arbitrary { Arb.nonEmptyList(Arb.boolean()).bind() to jacksonTypeRef>() } diff --git a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/OptionModuleTest.kt b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/OptionModuleTest.kt index 4aba638..18316f2 100644 --- a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/OptionModuleTest.kt +++ b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/OptionModuleTest.kt @@ -21,7 +21,8 @@ class OptionModuleTest : UnitSpec() { init { "serializing Option should be the same as serializing a nullable value" { - checkAll(Arb.option(Arb.choice(Arb.someObject(), Arb.int(), Arb.string(), Arb.boolean()))) { option -> + checkAll(Arb.option(Arb.choice(Arb.someObject(), Arb.int(), Arb.string(), Arb.boolean()))) { + option -> val actual = mapper.writeValueAsString(option) val expected = mapper.writeValueAsString(option.orNull()) @@ -30,14 +31,19 @@ class OptionModuleTest : UnitSpec() { } "serializing Option with Include.NON_ABSENT should honor such configuration and omit serialization when option is empty" { - val mapperWithSettings = ObjectMapper().registerModule(OptionModule).registerKotlinModule() - .setSerializationInclusion(JsonInclude.Include.NON_ABSENT) + val mapperWithSettings = + ObjectMapper() + .registerModule(OptionModule) + .registerKotlinModule() + .setSerializationInclusion(JsonInclude.Include.NON_ABSENT) data class Wrapper(val option: Option) - checkAll(Arb.option(Arb.choice(Arb.someObject(), Arb.int(), Arb.string(), Arb.boolean()))) { option -> + checkAll(Arb.option(Arb.choice(Arb.someObject(), Arb.int(), Arb.string(), Arb.boolean()))) { + option -> val actual = mapperWithSettings.writeValueAsString(Wrapper(option)) - val expected = option.fold({ "{}" }, { mapperWithSettings.writeValueAsString(Wrapper(it.some())) }) + val expected = + option.fold({ "{}" }, { mapperWithSettings.writeValueAsString(Wrapper(it.some())) }) actual shouldBe expected } diff --git a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/ValidatedModuleTest.kt b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/ValidatedModuleTest.kt index bc71768..aa51806 100644 --- a/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/ValidatedModuleTest.kt +++ b/arrow-integrations-jackson-module/src/test/kotlin/arrow/integrations/jackson/module/ValidatedModuleTest.kt @@ -27,12 +27,11 @@ import io.kotest.property.checkAll class ValidatedModuleTest : FunSpec() { init { context("json serialization / deserialization") { - test("should round-trip") { - checkAll(arbTestClass) { it.shouldRoundTrip(mapper) } - } + test("should round-trip") { checkAll(arbTestClass) { it.shouldRoundTrip(mapper) } } test("should round-trip nullable types") { - checkAll(Arb.validated(arbFoo.orNull(), arbBar.orNull())) { validated: Validated -> + checkAll(Arb.validated(arbFoo.orNull(), arbBar.orNull())) { validated: Validated + -> validated.shouldRoundTrip(mapper) } } @@ -42,26 +41,24 @@ class ValidatedModuleTest : FunSpec() { } test("should round-trip nested validated types") { - checkAll( - Arb.validated( - Arb.int(), - Arb.validated(Arb.int(), Arb.string()).orNull() - ) - ) { validated: Validated?> -> + checkAll(Arb.validated(Arb.int(), Arb.validated(Arb.int(), Arb.string()).orNull())) { + validated: Validated?> -> validated.shouldRoundTrip(mapper) } } test("should serialize with configurable invalid / valid field name") { checkAll( - Arb.pair( - Arb.string(10, Codepoint.az()), - Arb.string(10, Codepoint.az()) - ).filter { it.first != it.second } + Arb.pair(Arb.string(10, Codepoint.az()), Arb.string(10, Codepoint.az())).filter { + it.first != it.second + } ) { (invalidFieldName, validFieldName) -> - val mapper = ObjectMapper().registerKotlinModule().registerArrowModule( - validatedModuleConfig = ValidatedModuleConfig(invalidFieldName, validFieldName) - ) + val mapper = + ObjectMapper() + .registerKotlinModule() + .registerArrowModule( + validatedModuleConfig = ValidatedModuleConfig(invalidFieldName, validFieldName) + ) mapper.writeValueAsString(5.invalid()) shouldBe """{"$invalidFieldName":5}""" mapper.writeValueAsString("hello".valid()) shouldBe """{"$validFieldName":"hello"}""" @@ -70,15 +67,15 @@ class ValidatedModuleTest : FunSpec() { test("should round-trip with configurable invalid / valid field name") { checkAll( - Arb.pair( - Arb.string(10, Codepoint.az()), - Arb.string(10, Codepoint.az()) - ).filter { it.first != it.second }, + Arb.pair(Arb.string(10, Codepoint.az()), Arb.string(10, Codepoint.az())).filter { + it.first != it.second + }, arbTestClass ) { (invalidFieldName, validFieldName), testClass -> - val mapper = ObjectMapper() - .registerKotlinModule() - .registerArrowModule(EitherModuleConfig(invalidFieldName, validFieldName)) + val mapper = + ObjectMapper() + .registerKotlinModule() + .registerArrowModule(EitherModuleConfig(invalidFieldName, validFieldName)) testClass.shouldRoundTrip(mapper) } @@ -115,23 +112,19 @@ class ValidatedModuleTest : FunSpec() { } } - private data class Foo(@get:JsonProperty("foo") val fooValue: Option, val otherValue: String) + private data class Foo( + @get:JsonProperty("foo") val fooValue: Option, + val otherValue: String + ) private data class Bar(val first: Int, val second: String, val third: Boolean) private data class TestClass(val validated: Validated) private val arbFoo: Arb = arbitrary { - Foo( - Arb.option(Arb.int()).bind(), - Arb.string().bind() - ) + Foo(Arb.option(Arb.int()).bind(), Arb.string().bind()) } private val arbBar: Arb = arbitrary { - Bar( - Arb.int().bind(), - Arb.string(0..100, Codepoint.alphanumeric()).bind(), - Arb.boolean().bind() - ) + Bar(Arb.int().bind(), Arb.string(0..100, Codepoint.alphanumeric()).bind(), Arb.boolean().bind()) } private val arbTestClass: Arb = arbitrary { diff --git a/arrow-integrations-retrofit-adapter/build.gradle b/arrow-integrations-retrofit-adapter/build.gradle deleted file mode 100644 index 7a31ffa..0000000 --- a/arrow-integrations-retrofit-adapter/build.gradle +++ /dev/null @@ -1,33 +0,0 @@ -plugins { - id "org.jetbrains.kotlin.jvm" - id "org.jlleitschuh.gradle.ktlint" -} - -apply from: "$SUB_PROJECT" -// apply from: "$DOC_CREATION" -apply from: "$PUBLICATION" -// apply from: "$ANIMALSNIFFER" - -dependencies { - compile "io.arrow-kt:arrow-fx-coroutines:$ARROW_VERSION" - compile "io.arrow-kt:arrow-annotations:$ARROW_VERSION" - compile "com.squareup.retrofit2:retrofit:$RETROFIT_VERSION" - compileOnly "io.arrow-kt:arrow-meta:$ARROW_VERSION" - testCompileOnly "io.arrow-kt:arrow-meta:$ARROW_VERSION" - testCompile "io.arrow-kt:arrow-core-test:$ARROW_VERSION" - testCompile "com.squareup.retrofit2:converter-gson:$RETROFIT_VERSION" - testCompile "com.squareup.okhttp3:mockwebserver:$MOCKWEBSERVER_VERSION" - testCompile "io.arrow-kt:arrow-fx-rx2:$ARROW_VERSION" - testCompile "io.arrow-kt:arrow-fx-coroutines:$ARROW_VERSION" -} - -// TODO -// -- Gradle Animal Sniffer Plugin: https://github.com/xvik/gradle-animalsniffer-plugin -apply plugin: 'ru.vyarus.animalsniffer' -apply plugin: 'java' -animalsniffer { - ignore 'java.lang.*' -} -dependencies { - signature 'net.sf.androidscents.signature:android-api-level-21:5.0.1_r2@signature' -} diff --git a/arrow-integrations-retrofit-adapter/build.gradle.kts b/arrow-integrations-retrofit-adapter/build.gradle.kts new file mode 100644 index 0000000..d21183c --- /dev/null +++ b/arrow-integrations-retrofit-adapter/build.gradle.kts @@ -0,0 +1,32 @@ +/* +plugins { + id "org.jetbrains.kotlin.jvm" + id "org.jlleitschuh.gradle.ktlint" +} + +// apply from: "$ANIMALSNIFFER" + +dependencies { + compile "io.arrow-kt:arrow-fx-coroutines:1.0.1" + compile "io.arrow-kt:arrow-annotations:1.0.1" + compile "com.squareup.retrofit2:retrofit:$2.8.1" + compileOnly "io.arrow-kt:arrow-meta:1.0.1" + testCompileOnly "io.arrow-kt:arrow-meta:1.0.1" + testCompile "io.arrow-kt:arrow-core-test:1.0.1" + testCompile "com.squareup.retrofit2:converter-gson:$2.8.1" + testCompile "com.squareup.okhttp3:mockwebserver:3.13.1" + testCompile "io.arrow-kt:arrow-fx-rx2:1.0.1" + testCompile "io.arrow-kt:arrow-fx-coroutines:1.0.1" +} + +// TODO +// -- Gradle Animal Sniffer Plugin: https://github.com/xvik/gradle-animalsniffer-plugin +apply plugin: 'ru.vyarus.animalsniffer' +apply plugin: 'java' +animalsniffer { + ignore 'java.lang.*' +} +dependencies { + signature 'net.sf.androidscents.signature:android-api-level-21:5.0.1_r2@signature' +} +*/ diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 787372f..0000000 --- a/build.gradle +++ /dev/null @@ -1,25 +0,0 @@ -plugins { - id "org.jetbrains.kotlin.jvm" version "$KOTLIN_VERSION" - id "org.jetbrains.kotlin.kapt" version "$KOTLIN_VERSION" apply false - id "org.jlleitschuh.gradle.ktlint" version "$KTLINT_GRADLE_VERSION" apply false - id "org.jetbrains.dokka" version "$DOKKA_VERSION" - id "ru.vyarus.animalsniffer" version "$ANIMALS_SNIFFER_VERSION" apply false -} - -apply from: "$ROOT_PROJECT" - -subprojects { - dokka { - outputFormat = 'jekyll' - outputDirectory = "${rootDir}/build/apidocs" - configuration { - includes = ['README.md'] - reportUndocumented = false - sourceLink { - path = "src/main/kotlin" - url = "https://github.com/arrow-kt/arrow/blob/main/${relativeProjectPath('src/main/kotlin')}" - lineSuffix = "#L" - } - } - } -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..1c1bf9f --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,39 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +@Suppress("DSL_SCOPE_VIOLATION") +plugins { + alias(libs.plugins.kotlin.jvm) apply false + alias(libs.plugins.dokka) apply false + alias(libs.plugins.arrowGradleConfig.nexus) + alias(libs.plugins.arrowGradleConfig.formatter) + alias(libs.plugins.arrowGradleConfig.versioning) + alias(libs.plugins.kotlin.binaryCompatibilityValidator) +} + +allprojects { + repositories { + mavenCentral() + maven(url = "https://oss.sonatype.org/content/repositories/snapshots/") + } + + group = property("projects.group").toString() +} + + +tasks { + withType { + maxParallelForks = Runtime.getRuntime().availableProcessors() + useJUnitPlatform() + testLogging { + setExceptionFormat("full") + setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError")) + } + } + withType { + kotlinOptions { + jvmTarget = "1.8" + } + sourceCompatibility = JavaVersion.VERSION_1_8.toString() + targetCompatibility = JavaVersion.VERSION_1_8.toString() + } +} diff --git a/gradle.properties b/gradle.properties index cca92f6..bd542d7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,33 +1,14 @@ # Package definitions -GROUP=io.arrow-kt -VERSION_NAME=1.0.0-SNAPSHOT -LATEST_VERSION=0.13.2 -# Versions -ANIMALS_SNIFFER_VERSION=1.5.0 -ARROW_VERSION=1.0.0 -DOKKA_VERSION=0.10.0 -JACKSON_MODULE_KOTLIN_VERSION=2.13.1 -KOTEST_VERSION=5.1.0 -KOTLIN_VERSION=1.6.10 -KTLINT_GRADLE_VERSION=9.2.1 -KTLINT_VERSION=0.39.0 -MOCKWEBSERVER_VERSION=3.13.1 -RETROFIT_VERSION=2.8.1 - -# Publication -RELEASE_REPOSITORY=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -SNAPSHOT_REPOSITORY=https://oss.sonatype.org/content/repositories/snapshots/ -# Pomfile definitions -POM_DESCRIPTION=Functional companion to Kotlin's Standard Library -POM_URL=https://github.com/arrow-kt/arrow/ -POM_SCM_URL=https://github.com/arrow-kt/arrow/ -POM_SCM_CONNECTION=scm:git:git://github.com/arrow-kt/arrow.git -POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/arrow-kt/arrow.git -POM_LICENCE_NAME=The Apache Software License, Version 2.0 -POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt -POM_LICENCE_DIST=repo -POM_DEVELOPER_ID=arrow-kt -POM_DEVELOPER_NAME=The Arrow Authors +projects.group=io.arrow-kt +pom.description=Arrow Integrations +pom.url=https://github.com/arrow-kt/arrow-integrations +pom.smc.url=https://github.com/arrow-kt/arrow-integrations +pom.smc.connection=scm:git:git://github.com/arrow-kt/arrow-integrations.git +pom.smc.developerConnection=scm:git:ssh://git@github.com/arrow-kt/arrow-integrations.git +pom.license.name=The Apache Software License, Version 2.0 +pom.license.url=http://www.apache.org/licenses/LICENSE-2.0.txt +pom.developer.id=arrow-integrations +pom.developer.name=The Arrow Integrations Authors # Gradle options org.gradle.jvmargs=-Xmx4g @@ -42,9 +23,3 @@ kotlin.incremental=true #Parallelism needs to be set to 1 since the concurrent tests in arrow-effects become flaky otherwise kotest.framework.parallelism=1 kotlin.stdlib.default.dependency=false - -COMMON_SETUP=https://raw.githubusercontent.com/arrow-kt/arrow/0.13.2/arrow-libs/gradle/setup.gradle -ROOT_PROJECT=https://raw.githubusercontent.com/arrow-kt/arrow/0.13.2/arrow-libs/gradle/main.gradle -SUB_PROJECT=https://raw.githubusercontent.com/arrow-kt/arrow/0.13.2/arrow-libs/gradle/subproject.gradle -PUBLICATION=https://raw.githubusercontent.com/arrow-kt/arrow/0.13.2/arrow-libs/gradle/publication.gradle -ANIMALSNIFFER=https://raw.githubusercontent.com/arrow-kt/arrow/0.13.2/arrow-libs/gradle/animalsniffer.gradle diff --git a/gradle/projects.libs.versions.toml b/gradle/projects.libs.versions.toml new file mode 100644 index 0000000..f01d6f7 --- /dev/null +++ b/gradle/projects.libs.versions.toml @@ -0,0 +1,36 @@ +[versions] +arrow = "1.0.1" +dokka = "1.6.0" +arrowGradleConfig = "0.10.0" +kotlin = "1.6.20" +kotest = "5.2.2" +kotlinBinaryCompatibilityValidator = "0.8.0" +detekt = "1.19.0" +animalsniffer = "1.5.4" +jacksonModuleKotlin = "2.13.2" +animalsnifferAnnoation = "1.21" + +[libraries] +arrowAnnotations = { module = "io.arrow-kt:arrow-annotations", version.ref = "arrow" } +arrowCore = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" } +arrowCoreTest = { module = "io.arrow-kt:arrow-core-test", version.ref = "arrow" } +arrowOptics = { module = "io.arrow-kt:arrow-optics", version.ref = "arrow" } +jacksonModuleKotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jacksonModuleKotlin" } +kotest-assertionsCore = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" } +kotest-frameworkEngine = { module = "io.kotest:kotest-framework-engine", version.ref = "kotest" } +kotest-property = { module = "io.kotest:kotest-property", version.ref = "kotest" } +kotest-runnerJUnit5 = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" } +animalsniffer-annotation = {module = "org.codehaus.mojo:animal-sniffer-annotations", version.ref = "animalsnifferAnnoation"} + +[plugins] +dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +arrowGradleConfig-formatter = { id = "io.arrow-kt.arrow-gradle-config-formatter", version.ref = "arrowGradleConfig" } +arrowGradleConfig-kotlin = { id = "io.arrow-kt.arrow-gradle-config-kotlin", version.ref = "arrowGradleConfig" } +arrowGradleConfig-nexus = { id = "io.arrow-kt.arrow-gradle-config-nexus", version.ref = "arrowGradleConfig" } +arrowGradleConfig-publish = { id = "io.arrow-kt.arrow-gradle-config-publish", version.ref = "arrowGradleConfig" } +arrowGradleConfig-versioning = { id = "io.arrow-kt.arrow-gradle-config-versioning", version.ref = "arrowGradleConfig" } +kotlin-binaryCompatibilityValidator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "kotlinBinaryCompatibilityValidator" } +detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } +animalsniffer = { id = "ru.vyarus.animalsniffer", version.ref = "animalsniffer" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4e1cc9d..00e33ed 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index d24185f..0000000 --- a/settings.gradle +++ /dev/null @@ -1,5 +0,0 @@ -rootProject.name = 'arrow-integrations-lib' - -include 'arrow-integrations-jackson-module' -// include 'arrow-integrations-retrofit-adapter' -include 'arrow-docs' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..93196b2 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,28 @@ +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") +enableFeaturePreview("VERSION_CATALOGS") + +pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + } +} + +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("gradle/projects.libs.versions.toml")) + val kotlinVersion: String? by settings + kotlinVersion?.let { version("kotlin", it) } + } + } + + repositories { + mavenCentral() + } +} + +rootProject.name = "arrow-integrations" + +include(":arrow-integrations-jackson-module") +// include("arrow-integrations-retrofit-adapter")