├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .editorconfig ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ └── build.yml ├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src ├── main ├── java │ └── io │ │ └── vavr │ │ └── jackson │ │ └── datatype │ │ ├── VavrModule.java │ │ ├── VavrTypeModifier.java │ │ ├── deserialize │ │ ├── ArrayDeserializer.java │ │ ├── CharSeqDeserializer.java │ │ ├── EitherDeserializer.java │ │ ├── LazyDeserializer.java │ │ ├── MapDeserializer.java │ │ ├── MaplikeDeserializer.java │ │ ├── MultimapDeserializer.java │ │ ├── OptionDeserializer.java │ │ ├── PriorityQueueDeserializer.java │ │ ├── SeqDeserializer.java │ │ ├── SerializableDeserializer.java │ │ ├── SetDeserializer.java │ │ ├── Tuple0Deserializer.java │ │ ├── Tuple1Deserializer.java │ │ ├── Tuple2Deserializer.java │ │ ├── Tuple3Deserializer.java │ │ ├── Tuple4Deserializer.java │ │ ├── Tuple5Deserializer.java │ │ ├── Tuple6Deserializer.java │ │ ├── Tuple7Deserializer.java │ │ ├── Tuple8Deserializer.java │ │ ├── TupleDeserializer.java │ │ ├── ValueDeserializer.java │ │ └── VavrDeserializers.java │ │ └── serialize │ │ ├── ArraySerializer.java │ │ ├── CharSeqSerializer.java │ │ ├── EitherSerializer.java │ │ ├── HListSerializer.java │ │ ├── LazySerializer.java │ │ ├── MapSerializer.java │ │ ├── MultimapSerializer.java │ │ ├── OptionSerializer.java │ │ ├── SerializableSerializer.java │ │ ├── Tuple0Serializer.java │ │ ├── Tuple1Serializer.java │ │ ├── Tuple2Serializer.java │ │ ├── Tuple3Serializer.java │ │ ├── Tuple4Serializer.java │ │ ├── Tuple5Serializer.java │ │ ├── Tuple6Serializer.java │ │ ├── Tuple7Serializer.java │ │ ├── Tuple8Serializer.java │ │ ├── TupleSerializer.java │ │ ├── UnwrappingOptionSerializer.java │ │ ├── ValueSerializer.java │ │ └── VavrSerializers.java └── resources │ └── META-INF │ └── services │ └── com.fasterxml.jackson.databind.Module └── test └── java ├── generator ├── BindingClass.java ├── ExtFieldsPojo.java ├── Generator.java ├── ParameterizedPojo.java ├── PolymorphicPojo.java ├── SimplePojo.java └── utils │ ├── Initializer.java │ ├── PoetHelpers.java │ └── Serializer.java └── io └── vavr └── jackson ├── datatype ├── BaseTest.java ├── CharSeqTest.java ├── EitherTest.java ├── FunctionTest.java ├── LazyTest.java ├── MixedTest.java ├── OptionJsonMergeTest.java ├── OptionPlainTest.java ├── OptionTest.java ├── PriorityQueueTest.java ├── ScalarTest.java ├── SerializationFeatureTest.java ├── ServiceLoaderTest.java ├── bean │ ├── AbstractContentTest.java │ ├── BeanAnnotationTest.java │ ├── BeanTest.java │ ├── ComplexBeanTest.java │ └── ComplexClass.java ├── docs │ └── ReadmeTest.java ├── map │ ├── HashMapJsonMergeTest.java │ ├── HashMapTest.java │ ├── LinkedHashMapJsonMergeTest.java │ ├── LinkedHashMapTest.java │ ├── MapJsonMergeTest.java │ ├── MapTest.java │ ├── TreeMapJsonMergeTest.java │ └── TreeMapTest.java ├── multimap │ ├── HashMultimapTest.java │ ├── LinkedHashMultimapTest.java │ ├── MultimapTest.java │ └── TreeMultimapTest.java ├── seq │ ├── ArrayJsonMergeTest.java │ ├── ArrayTest.java │ ├── IndexedSeqJsonMergeTest.java │ ├── IndexedSeqTest.java │ ├── ListJsonMergeTest.java │ ├── ListTest.java │ ├── QueueJsonMergeTest.java │ ├── QueueTest.java │ ├── SeqJsonMergeTest.java │ ├── SeqTest.java │ ├── StreamJsonMergeTest.java │ ├── StreamTest.java │ ├── VectorJsonMergeTest.java │ └── VectorTest.java ├── set │ ├── HashSetJsonMergeTest.java │ ├── HashSetTest.java │ ├── LinkedHashSetJsonMergeTest.java │ ├── LinkedHashSetTest.java │ ├── SetJsonMergeTest.java │ ├── SetTest.java │ ├── TreeSetJsonMergeTest.java │ └── TreeSetTest.java └── tuples │ ├── Tuple1Test.java │ ├── Tuple2Test.java │ ├── Tuple3Test.java │ ├── Tuple4Test.java │ ├── Tuple5Test.java │ ├── Tuple6Test.java │ ├── Tuple7Test.java │ ├── Tuple8Test.java │ ├── TupleTest.java │ └── TupleXTest.java ├── generated ├── BindingClassTest.java ├── ExtFieldsPojoTest.java ├── ParameterizedPojoTest.java ├── PolymorphicPojoTest.java └── SimplePojoTest.java └── issues ├── Issue141Test.java ├── Issue142Test.java ├── Issue149Test.java └── Issue154Test.java /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG VARIANT=17 2 | FROM mcr.microsoft.com/vscode/devcontainers/java:0-${VARIANT} 3 | 4 | ARG NODE_VERSION="none" 5 | RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi 6 | 7 | ARG USER=vscode 8 | VOLUME /home/$USER/.m2 9 | VOLUME /home/$USER/.gradle 10 | 11 | ARG JAVA_VERSION=23.0.2-tem 12 | RUN sudo mkdir /home/$USER/.m2 /home/$USER/.gradle && sudo chown $USER:$USER /home/$USER/.m2 /home/$USER/.gradle 13 | RUN bash -lc '. /usr/local/sdkman/bin/sdkman-init.sh && sdk install java $JAVA_VERSION && sdk use java $JAVA_VERSION' -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/java 3 | { 4 | "name": "Java", 5 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile 6 | //https://mcr.microsoft.com/v2/vscode/devcontainers/java/tags/list 7 | //"image": "mcr.microsoft.com/devcontainers/java:21", 8 | "dockerFile": "Dockerfile", 9 | "build": { 10 | "args": { 11 | "NODE_VERSION": "22.11.0" 12 | } 13 | }, 14 | "hostRequirements": { 15 | "cpus": 2 16 | }, 17 | "features": { 18 | "ghcr.io/devcontainers/features/java:1": { 19 | "version": "none", 20 | "installMaven": "true", 21 | "installGradle": "true" 22 | }, 23 | "ghcr.io/devcontainers/features/sshd:1": { 24 | "version": "latest" 25 | }, 26 | "ghcr.io/devcontainers/features/docker-in-docker:2": { 27 | "version": "latest", 28 | "dockerDashComposeVersion": "v2" 29 | } 30 | }, 31 | "customizations": { 32 | "vscode": { 33 | "extensions": [ 34 | "vscjava.vscode-java-pack", 35 | "vscjava.vscode-java-debug", 36 | "vscjava.vscode-maven", 37 | "vscjava.vscode-gradle", 38 | "vscjava.vscode-java-dependency", 39 | "vscjava.vscode-java-test", 40 | "vscjava.vscode-spring-boot-dashboard", 41 | "vscjava.vscode-spring-initializr", 42 | "redhat.java", 43 | "vmware.vscode-boot-dev-pack", 44 | "vmware.vscode-spring-boot", 45 | "ms-azuretools.vscode-docker", 46 | "redhat.vscode-xml", 47 | "redhat.vscode-yaml", 48 | "editorconfig.editorconfig", 49 | "github.copilot", 50 | "github.copilot-chat" 51 | ] 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.java] 2 | indent_size = 4 3 | indent_style = space 4 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @pivovarit 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "maven" 4 | target-branch: "main" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | time: "02:00" 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | target-branch: "main" 12 | schedule: 13 | interval: "daily" 14 | time: "02:00" 15 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build and test 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | merge_group: 11 | 12 | jobs: 13 | build: 14 | name: "Compile against JDKs and OSes" 15 | strategy: 16 | matrix: 17 | os: [ubuntu-latest, macos-latest] 18 | java: [8, 11, 17, 21, 24] 19 | exclude: 20 | - java: 8 21 | os: macos-latest 22 | fail-fast: false 23 | runs-on: ${{ matrix.os }} 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: actions/setup-java@v4 27 | with: 28 | distribution: temurin 29 | java-version: ${{ matrix.java }} 30 | cache: maven 31 | 32 | - name: Build with Maven 33 | run: mvn --batch-mode clean verify 34 | 35 | test: 36 | name: "Test" 37 | needs: [build] 38 | runs-on: ubuntu-latest 39 | strategy: 40 | matrix: 41 | java: [8, 11, 17, 21, 24] 42 | fasterxmlVersion: [2.18.3, 2.19.0] 43 | fail-fast: false 44 | 45 | steps: 46 | - uses: actions/checkout@v4 47 | - uses: actions/setup-java@v4 48 | with: 49 | java-version: ${{ matrix.java }} 50 | distribution: temurin 51 | cache: maven 52 | 53 | - name: Run tests with specific Jackson version 54 | run: mvn --batch-mode clean verify -DfasterxmlVersion=${{ matrix.fasterxmlVersion }} 55 | 56 | results: 57 | if: ${{ always() }} 58 | runs-on: ubuntu-latest 59 | name: Verification Results 60 | needs: [test] 61 | steps: 62 | - name: Check test job status 63 | run: | 64 | if [[ "${{ needs.test.result }}" == "success" || "${{ needs.test.result }}" == "skipped" ]]; then 65 | exit 0 66 | else 67 | exit 1 68 | fi 69 | 70 | deploy-snapshot: 71 | runs-on: ubuntu-latest 72 | needs: results 73 | if: github.ref == 'refs/heads/main' 74 | 75 | steps: 76 | - uses: actions/checkout@v4 77 | - name: Setup JDK 78 | uses: actions/setup-java@v4 79 | with: 80 | distribution: 'temurin' 81 | java-version: '21' 82 | cache: 'maven' 83 | server-id: central 84 | server-username: CENTRAL_USERNAME 85 | server-password: CENTRAL_PASSWORD 86 | gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} 87 | 88 | - name: Deploy Snapshot 89 | run: mvn -B --no-transfer-progress -Pmaven-central-release -DskipTests=true deploy 90 | env: 91 | CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }} 92 | CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }} 93 | MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} 94 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | out 3 | .gradle 4 | .idea 5 | *.iml 6 | *.ipr 7 | *.iws 8 | 9 | target 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vavr-jackson 2 | 3 | [![Build](https://github.com/vavr-io/vavr-jackson/actions/workflows/build.yml/badge.svg)](https://github.com/vavr-io/vavr-jackson/actions/workflows/build.yml) 4 | ![Maven Central Version](https://img.shields.io/maven-central/v/io.vavr/vavr-jackson?versionPrefix=0) 5 | [![Coverage Status](https://codecov.io/github/vavr-io/vavr-jackson/coverage.svg?branch=master)](https://codecov.io/github/vavr-io/vavr-jackson?branch=master) 6 | 7 | Jackson datatype module for [Vavr](https://vavr.io/) library 8 | 9 | [![Stargazers over time](https://starchart.cc/vavr-io/vavr-jackson.svg?variant=adaptive)](https://starchart.cc/vavr-io/vavr-jackson) 10 | 11 | ## Usage 12 | 13 | ### Maven 14 | 15 | ```xml 16 | 17 | io.vavr 18 | vavr-jackson 19 | 0.10.3 20 | 21 | ``` 22 | 23 | ### Gradle 24 | 25 | ```groovy 26 | compile("io.vavr:vavr-jackson:0.10.3") 27 | ``` 28 | 29 | ### Registering module 30 | Just register a new instance of VavrModule 31 | ```java 32 | ObjectMapper mapper = new ObjectMapper(); 33 | mapper.registerModule(new VavrModule()); 34 | ``` 35 | 36 | ### Serialization/deserialization 37 | 38 | 39 | 40 | ```java 41 | String json = mapper.writeValueAsString(List.of(1)); 42 | // = [1] 43 | List restored = mapper.readValue(json, new TypeReference>() {}); 44 | // = List(1) 45 | ``` 46 | 47 | ## Using Developer Versions 48 | 49 | Developer versions can be found [here](https://oss.sonatype.org/content/repositories/snapshots/io/vavr/vavr-jackson). 50 | 51 | ### Maven 52 | 53 | ```xml 54 | 55 | io.vavr 56 | vavr-jackson 57 | 0.10.6-SNAPSHOT 58 | 59 | ``` 60 | 61 | Ensure that your `~/.m2/settings.xml` contains the following: 62 | 63 | ```xml 64 | 65 | 66 | allow-snapshots 67 | 68 | true 69 | 70 | 71 | 72 | snapshots-repo 73 | https://oss.sonatype.org/content/repositories/snapshots 74 | 75 | false 76 | 77 | 78 | true 79 | 80 | 81 | 82 | 83 | 84 | ``` 85 | 86 | ### Gradle 87 | 88 | ```groovy 89 | compile("io.vavr:vavr-jackson:0.10.6-SNAPSHOT") 90 | ``` 91 | 92 | Ensure that your `build.gradle` contains the following: 93 | 94 | ```groovy 95 | repositories { 96 | mavenCentral() 97 | maven { 98 | url "https://oss.sonatype.org/content/repositories/snapshots" 99 | } 100 | } 101 | ``` 102 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/VavrModule.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype; 21 | 22 | import com.fasterxml.jackson.databind.module.SimpleModule; 23 | import io.vavr.jackson.datatype.deserialize.VavrDeserializers; 24 | import io.vavr.jackson.datatype.serialize.VavrSerializers; 25 | 26 | public class VavrModule extends SimpleModule { 27 | 28 | private static final long serialVersionUID = 1L; 29 | 30 | public static class Settings { 31 | 32 | private boolean plainOption = true; 33 | private boolean deserializeNullAsEmptyCollection = false; 34 | 35 | public Settings useOptionInPlainFormat(boolean value) { 36 | plainOption = value; 37 | return this; 38 | } 39 | 40 | public Settings deserializeNullAsEmptyCollection(boolean value) { 41 | deserializeNullAsEmptyCollection = value; 42 | return this; 43 | } 44 | 45 | public boolean useOptionInPlainFormat() { 46 | return plainOption; 47 | } 48 | 49 | public boolean deserializeNullAsEmptyCollection() { 50 | return deserializeNullAsEmptyCollection; 51 | } 52 | } 53 | 54 | private final Settings settings; 55 | 56 | public VavrModule() { 57 | this(new Settings()); 58 | } 59 | 60 | public VavrModule(Settings settings) { 61 | this.settings = settings; 62 | } 63 | 64 | @Override 65 | public void setupModule(SetupContext context) { 66 | super.setupModule(context); 67 | context.addSerializers(new VavrSerializers(settings)); 68 | context.addDeserializers(new VavrDeserializers(settings)); 69 | context.addTypeModifier(new VavrTypeModifier()); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/VavrTypeModifier.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import com.fasterxml.jackson.databind.type.CollectionLikeType; 24 | import com.fasterxml.jackson.databind.type.MapLikeType; 25 | import com.fasterxml.jackson.databind.type.ReferenceType; 26 | import com.fasterxml.jackson.databind.type.TypeBindings; 27 | import com.fasterxml.jackson.databind.type.TypeFactory; 28 | import com.fasterxml.jackson.databind.type.TypeModifier; 29 | import io.vavr.Lazy; 30 | import io.vavr.collection.CharSeq; 31 | import io.vavr.collection.Map; 32 | import io.vavr.collection.Multimap; 33 | import io.vavr.collection.PriorityQueue; 34 | import io.vavr.collection.Seq; 35 | import io.vavr.collection.Set; 36 | import io.vavr.control.Option; 37 | 38 | import java.lang.reflect.Type; 39 | 40 | public class VavrTypeModifier extends TypeModifier { 41 | 42 | @Override 43 | public JavaType modifyType(JavaType type, Type jdkType, TypeBindings bindings, TypeFactory typeFactory) { 44 | final Class raw = type.getRawClass(); 45 | if (Seq.class.isAssignableFrom(raw) && CharSeq.class != raw) { 46 | return CollectionLikeType.upgradeFrom(type, type.containedTypeOrUnknown(0)); 47 | } 48 | if (Set.class.isAssignableFrom(raw)) { 49 | return CollectionLikeType.upgradeFrom(type, type.containedTypeOrUnknown(0)); 50 | } 51 | if (PriorityQueue.class.isAssignableFrom(raw)) { 52 | return CollectionLikeType.upgradeFrom(type, type.containedTypeOrUnknown(0)); 53 | } 54 | if (Map.class.isAssignableFrom(raw)) { 55 | return MapLikeType.upgradeFrom(type, type.containedTypeOrUnknown(0), type.containedTypeOrUnknown(1)); 56 | } 57 | if (Multimap.class.isAssignableFrom(raw)) { 58 | return MapLikeType.upgradeFrom(type, type.containedTypeOrUnknown(0), type.containedTypeOrUnknown(1)); 59 | } 60 | if (Lazy.class.isAssignableFrom(raw)) { 61 | return ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0)); 62 | } 63 | if (Option.class.isAssignableFrom(raw)) { 64 | return ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0)); 65 | } 66 | return type; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/CharSeqDeserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.core.JsonParser; 23 | import com.fasterxml.jackson.core.JsonToken; 24 | import com.fasterxml.jackson.databind.DeserializationContext; 25 | import com.fasterxml.jackson.databind.JavaType; 26 | import com.fasterxml.jackson.databind.JsonDeserializer; 27 | import com.fasterxml.jackson.databind.JsonMappingException; 28 | import com.fasterxml.jackson.databind.deser.ResolvableDeserializer; 29 | import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 30 | import com.fasterxml.jackson.databind.type.TypeFactory; 31 | import io.vavr.collection.CharSeq; 32 | 33 | import java.io.IOException; 34 | 35 | class CharSeqDeserializer extends StdDeserializer implements ResolvableDeserializer { 36 | 37 | private static final long serialVersionUID = 1L; 38 | 39 | private JsonDeserializer deserializer; 40 | 41 | CharSeqDeserializer(JavaType valueType) { 42 | super(valueType); 43 | } 44 | 45 | @Override 46 | public CharSeq deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 47 | Object obj = deserializer.deserialize(p, ctxt); 48 | if (obj instanceof String) { 49 | return CharSeq.of((String) obj); 50 | } else { 51 | throw JsonMappingException.from(p, String.format("Unexpected token (%s), expected %s: CharSeq can only be deserialized from String", p.getCurrentToken(), JsonToken.VALUE_STRING)); 52 | } 53 | } 54 | 55 | @Override 56 | public void resolve(DeserializationContext ctxt) throws JsonMappingException { 57 | deserializer = ctxt.findContextualValueDeserializer(TypeFactory.unknownType(), null); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/LazyDeserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.core.JsonParser; 23 | import com.fasterxml.jackson.databind.BeanProperty; 24 | import com.fasterxml.jackson.databind.DeserializationContext; 25 | import com.fasterxml.jackson.databind.JavaType; 26 | import com.fasterxml.jackson.databind.JsonDeserializer; 27 | import com.fasterxml.jackson.databind.JsonMappingException; 28 | import com.fasterxml.jackson.databind.deser.ContextualDeserializer; 29 | import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; 30 | import io.vavr.Lazy; 31 | 32 | import java.io.IOException; 33 | 34 | class LazyDeserializer extends ValueDeserializer> implements ContextualDeserializer { 35 | 36 | private static final long serialVersionUID = 1L; 37 | 38 | private final JavaType fullType; 39 | private final JavaType valueType; 40 | private final TypeDeserializer valueTypeDeserializer; 41 | private final JsonDeserializer valueDeserializer; 42 | 43 | LazyDeserializer(JavaType fullType, JavaType valueType, TypeDeserializer typeDeser, JsonDeserializer valueDeser) { 44 | super(valueType, 1); 45 | this.fullType = fullType; 46 | this.valueType = valueType; 47 | this.valueTypeDeserializer = typeDeser; 48 | this.valueDeserializer = valueDeser; 49 | } 50 | 51 | private LazyDeserializer(LazyDeserializer origin, TypeDeserializer typeDeser, JsonDeserializer valueDeser) { 52 | this(origin.fullType, origin.valueType, typeDeser, valueDeser); 53 | } 54 | 55 | @Override 56 | public Lazy deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 57 | Object value; 58 | if (valueTypeDeserializer == null) { 59 | value = valueDeserializer.deserialize(p, ctxt); 60 | } else { 61 | value = valueDeserializer.deserializeWithType(p, ctxt, valueTypeDeserializer); 62 | } 63 | return Lazy.of(() -> value); 64 | } 65 | 66 | @Override 67 | public Lazy getNullValue(DeserializationContext ctxt) { 68 | return Lazy.of(() -> null); 69 | } 70 | 71 | @Override 72 | public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { 73 | JsonDeserializer deser = valueDeserializer; 74 | TypeDeserializer typeDeser = valueTypeDeserializer; 75 | JavaType refType = valueType; 76 | 77 | if (deser == null) { 78 | deser = ctxt.findContextualValueDeserializer(refType, property); 79 | } else { // otherwise directly assigned, probably not contextual yet: 80 | deser = ctxt.handleSecondaryContextualization(deser, property, refType); 81 | } 82 | if (typeDeser != null) { 83 | typeDeser = typeDeser.forProperty(property); 84 | } 85 | return new LazyDeserializer(this, typeDeser, deser); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/MaplikeDeserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.BeanProperty; 23 | import com.fasterxml.jackson.databind.DeserializationContext; 24 | import com.fasterxml.jackson.databind.JavaType; 25 | import com.fasterxml.jackson.databind.JsonDeserializer; 26 | import com.fasterxml.jackson.databind.JsonMappingException; 27 | import com.fasterxml.jackson.databind.KeyDeserializer; 28 | import com.fasterxml.jackson.databind.deser.ContextualDeserializer; 29 | import com.fasterxml.jackson.databind.deser.ContextualKeyDeserializer; 30 | import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 31 | import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; 32 | import com.fasterxml.jackson.databind.type.MapLikeType; 33 | 34 | import java.io.Serializable; 35 | import java.util.Comparator; 36 | 37 | abstract class MaplikeDeserializer extends StdDeserializer implements ContextualDeserializer { 38 | 39 | private static final long serialVersionUID = 1L; 40 | 41 | final MapLikeType mapType; 42 | 43 | final Comparator keyComparator; 44 | final KeyDeserializer keyDeserializer; 45 | final TypeDeserializer elementTypeDeserializer; 46 | final JsonDeserializer elementDeserializer; 47 | 48 | MaplikeDeserializer(MapLikeType mapType, KeyDeserializer keyDeserializer, 49 | TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) { 50 | super(mapType); 51 | this.mapType = mapType; 52 | this.keyComparator = createKeyComparator(mapType.getKeyType()); 53 | this.keyDeserializer = keyDeserializer; 54 | this.elementTypeDeserializer = elementTypeDeserializer; 55 | this.elementDeserializer = elementDeserializer; 56 | } 57 | 58 | private Comparator createKeyComparator(JavaType keyType) { 59 | if (Comparable.class.isAssignableFrom(keyType.getRawClass())) { 60 | @SuppressWarnings("unchecked") 61 | Comparator comparator = (Comparator & Serializable) (o1, o2) -> ((Comparable) o1).compareTo(o2); 62 | return comparator; 63 | } else { 64 | return (Comparator & Serializable) (o1, o2) -> o1.toString().compareTo(o2.toString()); 65 | } 66 | } 67 | 68 | /** 69 | * Creates a new deserializer from the original one (this). 70 | * 71 | * @param keyDeserializer the new deserializer for key 72 | * @param elementTypeDeserializer the new deserializer for element type 73 | * @param elementDeserializer the new deserializer for element 74 | * 75 | * @return a new deserializer 76 | */ 77 | abstract MaplikeDeserializer createDeserializer(KeyDeserializer keyDeserializer, 78 | TypeDeserializer elementTypeDeserializer, 79 | JsonDeserializer elementDeserializer); 80 | 81 | @Override 82 | public JsonDeserializer createContextual(DeserializationContext context, BeanProperty property) throws JsonMappingException { 83 | KeyDeserializer keyDeser = keyDeserializer; 84 | if (keyDeser == null) { 85 | keyDeser = context.findKeyDeserializer(mapType.getKeyType(), property); 86 | } else if (keyDeser instanceof ContextualKeyDeserializer) { 87 | keyDeser = ((ContextualKeyDeserializer) keyDeser).createContextual(context, property); 88 | } 89 | 90 | TypeDeserializer elementTypeDeser = elementTypeDeserializer; 91 | if (elementTypeDeser != null) { 92 | elementTypeDeser = elementTypeDeser.forProperty(property); 93 | } 94 | JsonDeserializer elementDeser = elementDeserializer; 95 | if (elementDeser == null) { 96 | elementDeser = context.findContextualValueDeserializer(mapType.getContentType(), property); 97 | } else { 98 | elementDeser = context.handleSecondaryContextualization(elementDeser, property, mapType.getContentType()); 99 | } 100 | return createDeserializer(keyDeser, elementTypeDeser, elementDeser); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/MultimapDeserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.core.JsonParser; 23 | import com.fasterxml.jackson.core.JsonToken; 24 | import com.fasterxml.jackson.databind.DeserializationContext; 25 | import com.fasterxml.jackson.databind.JavaType; 26 | import com.fasterxml.jackson.databind.JsonDeserializer; 27 | import com.fasterxml.jackson.databind.JsonMappingException; 28 | import com.fasterxml.jackson.databind.KeyDeserializer; 29 | import com.fasterxml.jackson.databind.deser.ResolvableDeserializer; 30 | import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; 31 | import com.fasterxml.jackson.databind.type.MapLikeType; 32 | import io.vavr.Tuple; 33 | import io.vavr.Tuple2; 34 | import io.vavr.collection.HashMultimap; 35 | import io.vavr.collection.LinkedHashMultimap; 36 | import io.vavr.collection.Multimap; 37 | import io.vavr.collection.TreeMultimap; 38 | 39 | import java.io.IOException; 40 | import java.util.ArrayList; 41 | 42 | class MultimapDeserializer extends MaplikeDeserializer> implements ResolvableDeserializer { 43 | 44 | private static final long serialVersionUID = 1L; 45 | 46 | private JsonDeserializer containerDeserializer; 47 | 48 | MultimapDeserializer(MapLikeType mapType, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, 49 | JsonDeserializer elementDeserializer) { 50 | super(mapType, keyDeserializer, elementTypeDeserializer, elementDeserializer); 51 | } 52 | 53 | MultimapDeserializer(MultimapDeserializer origin, KeyDeserializer keyDeserializer, 54 | TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) { 55 | super(origin.mapType, keyDeserializer, elementTypeDeserializer, elementDeserializer); 56 | containerDeserializer = origin.containerDeserializer; 57 | } 58 | 59 | @Override 60 | MultimapDeserializer createDeserializer(KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, 61 | JsonDeserializer elementDeserializer) { 62 | return new MultimapDeserializer(this, keyDeserializer, elementTypeDeserializer, elementDeserializer); 63 | } 64 | 65 | @Override 66 | public void resolve(DeserializationContext ctxt) throws JsonMappingException { 67 | JavaType containerType = ctxt.getTypeFactory() 68 | .constructCollectionType(ArrayList.class, mapType.getContentType()); 69 | containerDeserializer = ctxt.findContextualValueDeserializer(containerType, null); 70 | } 71 | 72 | @Override 73 | public Multimap deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 74 | final java.util.List> result = new java.util.ArrayList<>(); 75 | while (p.nextToken() != JsonToken.END_OBJECT) { 76 | String name = p.getCurrentName(); 77 | Object key = keyDeserializer.deserializeKey(name, ctxt); 78 | p.nextToken(); 79 | ArrayList list = (ArrayList) containerDeserializer.deserialize(p, ctxt); 80 | for (Object elem : list) { 81 | result.add(Tuple.of(key, elem)); 82 | } 83 | } 84 | if (TreeMultimap.class.isAssignableFrom(handledType())) { 85 | return TreeMultimap.withSeq().ofEntries(keyComparator, result); 86 | } 87 | if (LinkedHashMultimap.class.isAssignableFrom(handledType())) { 88 | return LinkedHashMultimap.withSeq().ofEntries(result); 89 | } 90 | // default deserialization [...] -> Map 91 | return HashMultimap.withSeq().ofEntries(result); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/PriorityQueueDeserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import com.fasterxml.jackson.databind.JsonDeserializer; 25 | import com.fasterxml.jackson.databind.JsonMappingException; 26 | import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; 27 | import io.vavr.collection.PriorityQueue; 28 | 29 | import java.io.Serializable; 30 | import java.util.Comparator; 31 | import java.util.List; 32 | 33 | class PriorityQueueDeserializer extends ArrayDeserializer> { 34 | 35 | private static final long serialVersionUID = 1L; 36 | 37 | PriorityQueueDeserializer(JavaType collectionType, JavaType elementType, TypeDeserializer elementTypeDeserializer, 38 | JsonDeserializer elementDeserializer, boolean deserializeNullAsEmptyCollection) { 39 | super(collectionType, 1, elementType, elementTypeDeserializer, elementDeserializer, deserializeNullAsEmptyCollection); 40 | } 41 | 42 | /** 43 | * Creates a new deserializer from the original one. 44 | * 45 | * @param origin the original deserializer 46 | * @param elementTypeDeserializer the new deserializer for the element type 47 | * @param elementDeserializer the new deserializer for the element itself 48 | */ 49 | PriorityQueueDeserializer(PriorityQueueDeserializer origin, TypeDeserializer elementTypeDeserializer, 50 | JsonDeserializer elementDeserializer) { 51 | this(origin.collectionType, origin.elementType, elementTypeDeserializer, elementDeserializer, 52 | origin.deserializeNullAsEmptyCollection); 53 | } 54 | 55 | @SuppressWarnings("unchecked") 56 | @Override 57 | PriorityQueue create(List list, DeserializationContext ctxt) throws JsonMappingException { 58 | checkContainedTypeIsComparable(ctxt, collectionType.containedTypeOrUnknown(0)); 59 | return PriorityQueue.ofAll((Comparator & Serializable) (o1, o2) -> ((Comparable) o1).compareTo(o2), list); 60 | } 61 | 62 | @Override 63 | PriorityQueueDeserializer createDeserializer(TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) { 64 | return new PriorityQueueDeserializer(this, elementTypeDeserializer, elementDeserializer); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/SeqDeserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import com.fasterxml.jackson.databind.JsonDeserializer; 25 | import com.fasterxml.jackson.databind.JsonMappingException; 26 | import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; 27 | import io.vavr.collection.Array; 28 | import io.vavr.collection.IndexedSeq; 29 | import io.vavr.collection.Queue; 30 | import io.vavr.collection.Seq; 31 | import io.vavr.collection.Stream; 32 | import io.vavr.collection.Vector; 33 | 34 | import java.util.List; 35 | 36 | class SeqDeserializer extends ArrayDeserializer> { 37 | 38 | private static final long serialVersionUID = 1L; 39 | 40 | SeqDeserializer(JavaType collectionType, JavaType elementType, TypeDeserializer elementTypeDeserializer, 41 | JsonDeserializer elementDeserializer, boolean deserializeNullAsEmptyCollection) { 42 | super(collectionType, 1, elementType, elementTypeDeserializer, elementDeserializer, deserializeNullAsEmptyCollection); 43 | } 44 | 45 | /** 46 | * Creates a new deserializer from the original one. 47 | * 48 | * @param origin the original deserializer 49 | * @param elementTypeDeserializer the new deserializer for the element type 50 | * @param elementDeserializer the new deserializer for the element itself 51 | */ 52 | private SeqDeserializer(SeqDeserializer origin, TypeDeserializer elementTypeDeserializer, 53 | JsonDeserializer elementDeserializer) { 54 | this(origin.collectionType, origin.elementType, elementTypeDeserializer, elementDeserializer, 55 | origin.deserializeNullAsEmptyCollection); 56 | } 57 | 58 | @Override 59 | Seq create(List result, DeserializationContext ctxt) throws JsonMappingException { 60 | if (Array.class.isAssignableFrom(collectionType.getRawClass())) { 61 | return Array.ofAll(result); 62 | } 63 | if (Queue.class.isAssignableFrom(collectionType.getRawClass())) { 64 | return Queue.ofAll(result); 65 | } 66 | if (Stream.class.isAssignableFrom(collectionType.getRawClass())) { 67 | return Stream.ofAll(result); 68 | } 69 | if (Vector.class.isAssignableFrom(collectionType.getRawClass())) { 70 | return Vector.ofAll(result); 71 | } 72 | if (IndexedSeq.class.isAssignableFrom(collectionType.getRawClass())) { 73 | return Array.ofAll(result); 74 | } 75 | // default deserialization [...] -> Seq 76 | return io.vavr.collection.List.ofAll(result); 77 | } 78 | 79 | @Override 80 | SeqDeserializer createDeserializer(TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) { 81 | return new SeqDeserializer(this, elementTypeDeserializer, elementDeserializer); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/SerializableDeserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.core.JsonParser; 23 | import com.fasterxml.jackson.databind.DeserializationContext; 24 | import com.fasterxml.jackson.databind.JavaType; 25 | import com.fasterxml.jackson.databind.JsonDeserializer; 26 | import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 27 | 28 | import java.io.ByteArrayInputStream; 29 | import java.io.IOException; 30 | import java.io.ObjectInputStream; 31 | 32 | class SerializableDeserializer extends StdDeserializer { 33 | 34 | private static final long serialVersionUID = 1L; 35 | 36 | SerializableDeserializer(JavaType valueType) { 37 | super(valueType); 38 | } 39 | 40 | @Override 41 | public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 42 | JsonDeserializer deserializer = ctxt.findRootValueDeserializer(ctxt.constructType(byte[].class)); 43 | byte[] bytes = (byte[]) deserializer.deserialize(p, ctxt); 44 | return deserialize(bytes); 45 | } 46 | 47 | @SuppressWarnings("unchecked") 48 | private static T deserialize(byte[] objectData) { 49 | try { 50 | ObjectInputStream stream = new ObjectInputStream(new ByteArrayInputStream(objectData)); 51 | return (T) stream.readObject(); 52 | } catch (Exception x) { 53 | throw new IllegalStateException("Error deserializing object", x); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/SetDeserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import com.fasterxml.jackson.databind.JsonDeserializer; 25 | import com.fasterxml.jackson.databind.JsonMappingException; 26 | import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; 27 | import io.vavr.collection.HashSet; 28 | import io.vavr.collection.Set; 29 | 30 | import java.io.Serializable; 31 | import java.util.Comparator; 32 | import java.util.List; 33 | 34 | class SetDeserializer extends ArrayDeserializer> { 35 | 36 | private static final long serialVersionUID = 1L; 37 | 38 | SetDeserializer(JavaType collectionType, JavaType elementType, TypeDeserializer elementTypeDeserializer, 39 | JsonDeserializer elementDeserializer, boolean deserializeNullAsEmptyCollection) { 40 | super(collectionType, 1, elementType, elementTypeDeserializer, elementDeserializer, deserializeNullAsEmptyCollection); 41 | } 42 | 43 | /** 44 | * Creates a new deserializer from the original one. 45 | * 46 | * @param origin the original deserializer 47 | * @param elementTypeDeserializer the new deserializer for the element type 48 | * @param elementDeserializer the new deserializer for the element itself 49 | */ 50 | private SetDeserializer(SetDeserializer origin, TypeDeserializer elementTypeDeserializer, 51 | JsonDeserializer elementDeserializer) { 52 | this(origin.collectionType, origin.elementType, elementTypeDeserializer, elementDeserializer, 53 | origin.deserializeNullAsEmptyCollection); 54 | } 55 | 56 | @SuppressWarnings("unchecked") 57 | @Override 58 | Set create(List result, DeserializationContext ctx) throws JsonMappingException { 59 | if (io.vavr.collection.SortedSet.class.isAssignableFrom(collectionType.getRawClass())) { 60 | checkContainedTypeIsComparable(ctx, collectionType.containedTypeOrUnknown(0)); 61 | return io.vavr.collection.TreeSet.ofAll((Comparator & Serializable) (o1, o2) -> ((Comparable) o1).compareTo(o2), result); 62 | } 63 | if (io.vavr.collection.LinkedHashSet.class.isAssignableFrom(collectionType.getRawClass())) { 64 | return io.vavr.collection.LinkedHashSet.ofAll(result); 65 | } 66 | // default deserialization [...] -> Set 67 | return HashSet.ofAll(result); 68 | } 69 | 70 | @Override 71 | SetDeserializer createDeserializer(TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) { 72 | return new SetDeserializer(this, elementTypeDeserializer, elementDeserializer); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/Tuple0Deserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import io.vavr.Tuple; 25 | import io.vavr.Tuple0; 26 | 27 | import java.util.List; 28 | 29 | class Tuple0Deserializer extends TupleDeserializer { 30 | 31 | Tuple0Deserializer(JavaType valueType) { 32 | super(valueType); 33 | } 34 | 35 | @Override 36 | Tuple0 create(List list, DeserializationContext ctxt) { 37 | return Tuple.empty(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/Tuple1Deserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import io.vavr.Tuple; 25 | import io.vavr.Tuple1; 26 | 27 | import java.util.List; 28 | 29 | class Tuple1Deserializer extends TupleDeserializer> { 30 | 31 | Tuple1Deserializer(JavaType valueType) { 32 | super(valueType); 33 | } 34 | 35 | @Override 36 | Tuple1 create(List list, DeserializationContext ctxt) { 37 | return Tuple.of(list.get(0)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/Tuple2Deserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import io.vavr.Tuple; 25 | import io.vavr.Tuple2; 26 | 27 | import java.util.List; 28 | 29 | class Tuple2Deserializer extends TupleDeserializer> { 30 | 31 | Tuple2Deserializer(JavaType valueType) { 32 | super(valueType); 33 | } 34 | 35 | @Override 36 | Tuple2 create(List list, DeserializationContext ctxt) { 37 | return Tuple.of(list.get(0), list.get(1)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/Tuple3Deserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import io.vavr.Tuple; 25 | import io.vavr.Tuple3; 26 | 27 | import java.util.List; 28 | 29 | class Tuple3Deserializer extends TupleDeserializer> { 30 | 31 | Tuple3Deserializer(JavaType valueType) { 32 | super(valueType); 33 | } 34 | 35 | @Override 36 | Tuple3 create(List list, DeserializationContext ctxt) { 37 | return Tuple.of(list.get(0), list.get(1), list.get(2)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/Tuple4Deserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import io.vavr.Tuple; 25 | import io.vavr.Tuple4; 26 | 27 | import java.util.List; 28 | 29 | class Tuple4Deserializer extends TupleDeserializer> { 30 | 31 | Tuple4Deserializer(JavaType valueType) { 32 | super(valueType); 33 | } 34 | 35 | @Override 36 | Tuple4 create(List list, DeserializationContext ctxt) { 37 | return Tuple.of(list.get(0), list.get(1), list.get(2), list.get(3)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/Tuple5Deserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import io.vavr.Tuple; 25 | import io.vavr.Tuple5; 26 | 27 | import java.util.List; 28 | 29 | class Tuple5Deserializer extends TupleDeserializer> { 30 | 31 | Tuple5Deserializer(JavaType valueType) { 32 | super(valueType); 33 | } 34 | 35 | @Override 36 | Tuple5 create(List list, DeserializationContext ctxt) { 37 | return Tuple.of(list.get(0), list.get(1), list.get(2), list.get(3), list.get(4)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/Tuple6Deserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import io.vavr.Tuple; 25 | import io.vavr.Tuple6; 26 | 27 | import java.util.List; 28 | 29 | class Tuple6Deserializer extends TupleDeserializer> { 30 | 31 | Tuple6Deserializer(JavaType valueType) { 32 | super(valueType); 33 | } 34 | 35 | @Override 36 | Tuple6 create(List list, DeserializationContext ctxt) { 37 | return Tuple.of(list.get(0), list.get(1), list.get(2), list.get(3), list.get(4), list.get(5)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/Tuple7Deserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import io.vavr.Tuple; 25 | import io.vavr.Tuple7; 26 | 27 | import java.util.List; 28 | 29 | class Tuple7Deserializer extends TupleDeserializer> { 30 | 31 | Tuple7Deserializer(JavaType valueType) { 32 | super(valueType); 33 | } 34 | 35 | @Override 36 | Tuple7 create(List list, DeserializationContext ctxt) { 37 | return Tuple.of(list.get(0), list.get(1), list.get(2), list.get(3), list.get(4), list.get(5), list.get(6)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/Tuple8Deserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import io.vavr.Tuple; 25 | import io.vavr.Tuple8; 26 | 27 | import java.util.List; 28 | 29 | class Tuple8Deserializer extends TupleDeserializer> { 30 | 31 | Tuple8Deserializer(JavaType valueType) { 32 | super(valueType); 33 | } 34 | 35 | @Override 36 | Tuple8 create(List list, DeserializationContext ctxt) { 37 | return Tuple.of(list.get(0), list.get(1), list.get(2), list.get(3), list.get(4), list.get(5), list.get(6), list.get(7)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/TupleDeserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.core.JsonParser; 23 | import com.fasterxml.jackson.core.JsonToken; 24 | import com.fasterxml.jackson.databind.DeserializationContext; 25 | import com.fasterxml.jackson.databind.JavaType; 26 | import com.fasterxml.jackson.databind.JsonDeserializer; 27 | import io.vavr.Tuple0; 28 | import io.vavr.Tuple1; 29 | import io.vavr.Tuple2; 30 | import io.vavr.Tuple3; 31 | import io.vavr.Tuple4; 32 | import io.vavr.Tuple5; 33 | import io.vavr.Tuple6; 34 | import io.vavr.Tuple7; 35 | 36 | import java.io.IOException; 37 | import java.util.ArrayList; 38 | import java.util.List; 39 | 40 | import static com.fasterxml.jackson.core.JsonToken.END_ARRAY; 41 | import static com.fasterxml.jackson.core.JsonToken.VALUE_NULL; 42 | 43 | abstract class TupleDeserializer extends ValueDeserializer { 44 | 45 | private static final long serialVersionUID = 1L; 46 | 47 | private final JavaType javaType; 48 | 49 | TupleDeserializer(JavaType valueType) { 50 | super(valueType, arity(valueType)); 51 | this.javaType = valueType; 52 | } 53 | 54 | @Override 55 | public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 56 | List list = new ArrayList<>(); 57 | int ptr = 0; 58 | 59 | for (JsonToken jsonToken = p.nextToken(); jsonToken != END_ARRAY; jsonToken = p.nextToken()) { 60 | if (ptr >= deserializersCount()) { 61 | throw mappingException(ctxt, javaType.getRawClass(), jsonToken); 62 | } 63 | JsonDeserializer deserializer = deserializer(ptr++); 64 | Object value = (jsonToken != VALUE_NULL) ? deserializer.deserialize(p, ctxt) : deserializer.getNullValue(ctxt); 65 | list.add(value); 66 | } 67 | if (list.size() == deserializersCount()) { 68 | return create(list, ctxt); 69 | } else { 70 | throw mappingException(ctxt, javaType.getRawClass(), null); 71 | } 72 | } 73 | 74 | abstract T create(List list, DeserializationContext ctxt); 75 | 76 | private static int arity(JavaType valueType) { 77 | Class clz = valueType.getRawClass(); 78 | if (clz == Tuple0.class) { 79 | return 0; 80 | } else if (clz == Tuple1.class) { 81 | return 1; 82 | } else if (clz == Tuple2.class) { 83 | return 2; 84 | } else if (clz == Tuple3.class) { 85 | return 3; 86 | } else if (clz == Tuple4.class) { 87 | return 4; 88 | } else if (clz == Tuple5.class) { 89 | return 5; 90 | } else if (clz == Tuple6.class) { 91 | return 6; 92 | } else if (clz == Tuple7.class) { 93 | return 7; 94 | } else { 95 | return 8; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/deserialize/ValueDeserializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.deserialize; 21 | 22 | import com.fasterxml.jackson.core.JsonToken; 23 | import com.fasterxml.jackson.databind.DeserializationContext; 24 | import com.fasterxml.jackson.databind.JavaType; 25 | import com.fasterxml.jackson.databind.JsonDeserializer; 26 | import com.fasterxml.jackson.databind.JsonMappingException; 27 | import com.fasterxml.jackson.databind.deser.ResolvableDeserializer; 28 | import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 29 | 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | 33 | abstract class ValueDeserializer extends StdDeserializer implements ResolvableDeserializer { 34 | 35 | private static final long serialVersionUID = 1L; 36 | 37 | private final JavaType javaType; 38 | private final int typeCount; 39 | private final List> deserializers; 40 | 41 | ValueDeserializer(JavaType valueType, int typeCount) { 42 | super(valueType); 43 | this.javaType = valueType; 44 | this.typeCount = typeCount; 45 | this.deserializers = new ArrayList<>(typeCount); 46 | } 47 | 48 | int deserializersCount() { 49 | return deserializers.size(); 50 | } 51 | 52 | JsonDeserializer deserializer(int index) { 53 | return deserializers.get(index); 54 | } 55 | 56 | @Override 57 | public void resolve(DeserializationContext ctxt) throws JsonMappingException { 58 | // TODO rewrite this 59 | if (javaType.isCollectionLikeType() || javaType.isReferenceType()) { 60 | deserializers.add(ctxt.findRootValueDeserializer(javaType.getContentType())); 61 | return; 62 | } 63 | for (int i = 0; i < typeCount; i++) { 64 | JavaType containedType = javaType.containedTypeOrUnknown(i); 65 | deserializers.add(ctxt.findRootValueDeserializer(containedType)); 66 | } 67 | } 68 | 69 | // DEV-NOTE: original method is deprecated since 2.8 70 | static JsonMappingException mappingException(DeserializationContext ctxt, Class targetClass, JsonToken token) { 71 | String tokenDesc = (token == null) ? "" : String.format("%s token", token); 72 | return JsonMappingException.from(ctxt.getParser(), 73 | String.format("Can not deserialize instance of %s out of %s", 74 | _calcName(targetClass), tokenDesc)); 75 | } 76 | 77 | private static String _calcName(Class cls) { 78 | if (cls.isArray()) { 79 | return _calcName(cls.getComponentType()) + "[]"; 80 | } 81 | return cls.getName(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/ArraySerializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.BeanProperty; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import com.fasterxml.jackson.databind.JsonMappingException; 25 | import com.fasterxml.jackson.databind.JsonSerializer; 26 | import com.fasterxml.jackson.databind.SerializerProvider; 27 | import com.fasterxml.jackson.databind.ser.ContextualSerializer; 28 | import com.fasterxml.jackson.databind.type.CollectionLikeType; 29 | import com.fasterxml.jackson.databind.type.TypeFactory; 30 | import io.vavr.Value; 31 | 32 | import java.util.ArrayList; 33 | 34 | class ArraySerializer> extends ValueSerializer implements ContextualSerializer { 35 | 36 | private static final long serialVersionUID = 1L; 37 | private final CollectionLikeType collectionType; 38 | 39 | ArraySerializer(CollectionLikeType collectionType, BeanProperty property) { 40 | super(collectionType, property); 41 | this.collectionType = collectionType; 42 | } 43 | 44 | ArraySerializer(CollectionLikeType collectionType) { 45 | this(collectionType, null); 46 | } 47 | 48 | /** 49 | * Creates a new serializer from the original one. 50 | * 51 | * @param origin the original serializer 52 | * @param property the new bean property 53 | */ 54 | ArraySerializer(ArraySerializer origin, BeanProperty property) { 55 | this(origin.collectionType, property); 56 | } 57 | 58 | @Override 59 | Object toJavaObj(T value) { 60 | return value.toJavaList(); 61 | } 62 | 63 | @Override 64 | JavaType emulatedJavaType(TypeFactory typeFactory) { 65 | return typeFactory.constructCollectionType(ArrayList.class, collectionType.getContentType()); 66 | } 67 | 68 | @Override 69 | public boolean isEmpty(SerializerProvider provider, T value) { 70 | return value.isEmpty(); 71 | } 72 | 73 | @Override 74 | public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) 75 | throws JsonMappingException { 76 | if (property == beanProperty) { 77 | return this; 78 | } 79 | return new ArraySerializer<>(this, property); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/CharSeqSerializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import com.fasterxml.jackson.databind.SerializerProvider; 24 | import com.fasterxml.jackson.databind.type.TypeFactory; 25 | import io.vavr.collection.CharSeq; 26 | 27 | import java.io.IOException; 28 | 29 | class CharSeqSerializer extends ValueSerializer { 30 | 31 | private static final long serialVersionUID = 1L; 32 | 33 | CharSeqSerializer(JavaType type) { 34 | super(type); 35 | } 36 | 37 | @Override 38 | Object toJavaObj(CharSeq value) throws IOException { 39 | return value.toString(); 40 | } 41 | 42 | @Override 43 | JavaType emulatedJavaType(TypeFactory typeFactory) { 44 | return typeFactory.constructType(String.class); 45 | } 46 | 47 | @Override 48 | public boolean isEmpty(SerializerProvider provider, CharSeq value) { 49 | return value.isEmpty(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/EitherSerializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.core.JsonGenerator; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import com.fasterxml.jackson.databind.SerializerProvider; 25 | import io.vavr.control.Either; 26 | 27 | import java.io.IOException; 28 | 29 | class EitherSerializer extends HListSerializer> { 30 | 31 | private static final long serialVersionUID = 1L; 32 | 33 | EitherSerializer(JavaType type) { 34 | super(type); 35 | } 36 | 37 | @Override 38 | public void serialize(Either value, JsonGenerator gen, SerializerProvider provider) throws IOException { 39 | gen.writeStartArray(); 40 | if (value.isLeft()) { 41 | gen.writeString("left"); 42 | write(value.getLeft(), 0, gen, provider); 43 | } else { 44 | gen.writeString("right"); 45 | write(value.get(), 1, gen, provider); 46 | } 47 | gen.writeEndArray(); 48 | } 49 | 50 | @Override 51 | public boolean isEmpty(SerializerProvider provider, Either value) { 52 | return value.isEmpty(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/HListSerializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.core.JsonGenerator; 23 | import com.fasterxml.jackson.core.JsonToken; 24 | import com.fasterxml.jackson.databind.JavaType; 25 | import com.fasterxml.jackson.databind.JsonSerializer; 26 | import com.fasterxml.jackson.databind.SerializerProvider; 27 | import com.fasterxml.jackson.databind.jsontype.TypeSerializer; 28 | import com.fasterxml.jackson.databind.ser.std.StdSerializer; 29 | 30 | import java.io.IOException; 31 | 32 | abstract class HListSerializer extends StdSerializer { 33 | 34 | private static final long serialVersionUID = 1L; 35 | 36 | private final JavaType type; 37 | 38 | HListSerializer(JavaType type) { 39 | super(type); 40 | this.type = type; 41 | } 42 | 43 | void write(Object val, int containedTypeIndex, JsonGenerator gen, SerializerProvider provider) throws IOException { 44 | if (val != null) { 45 | if (type.containedTypeCount() > containedTypeIndex) { 46 | JsonSerializer ser; 47 | JavaType containedType = type.containedType(containedTypeIndex); 48 | if (containedType != null && containedType.hasGenericTypes()) { 49 | JavaType st = provider.constructSpecializedType(containedType, val.getClass()); 50 | ser = provider.findTypedValueSerializer(st, true, null); 51 | } else { 52 | ser = provider.findTypedValueSerializer(val.getClass(), true, null); 53 | } 54 | ser.serialize(val, gen, provider); 55 | } else { 56 | gen.writeObject(val); 57 | } 58 | } else { 59 | gen.writeNull(); 60 | } 61 | } 62 | 63 | @Override 64 | public void serializeWithType(T value, JsonGenerator gen, SerializerProvider serializers, 65 | TypeSerializer typeSer) throws IOException { 66 | typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.VALUE_STRING)); 67 | serialize(value, gen, serializers); 68 | typeSer.writeTypeSuffix(gen, typeSer.typeId(value, JsonToken.VALUE_STRING)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/LazySerializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.core.JsonGenerator; 23 | import com.fasterxml.jackson.databind.AnnotationIntrospector; 24 | import com.fasterxml.jackson.databind.BeanProperty; 25 | import com.fasterxml.jackson.databind.JavaType; 26 | import com.fasterxml.jackson.databind.JsonMappingException; 27 | import com.fasterxml.jackson.databind.JsonSerializer; 28 | import com.fasterxml.jackson.databind.MapperFeature; 29 | import com.fasterxml.jackson.databind.SerializerProvider; 30 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 31 | import com.fasterxml.jackson.databind.introspect.Annotated; 32 | import com.fasterxml.jackson.databind.jsontype.TypeSerializer; 33 | import com.fasterxml.jackson.databind.ser.ContextualSerializer; 34 | import io.vavr.Lazy; 35 | 36 | import java.io.IOException; 37 | 38 | class LazySerializer extends HListSerializer> implements ContextualSerializer { 39 | 40 | private static final long serialVersionUID = 1L; 41 | 42 | private final JavaType fullType; 43 | private final JavaType valueType; 44 | private final TypeSerializer valueTypeSerializer; 45 | private final JsonSerializer valueSerializer; 46 | 47 | @SuppressWarnings("unchecked") 48 | LazySerializer(JavaType fullType, JavaType valueType, TypeSerializer typeSer, JsonSerializer valueSer) { 49 | super(fullType); 50 | this.fullType = fullType; 51 | this.valueType = valueType; 52 | this.valueTypeSerializer = typeSer; 53 | this.valueSerializer = (JsonSerializer) valueSer; 54 | } 55 | 56 | @Override 57 | public void serialize(Lazy value, JsonGenerator gen, SerializerProvider provider) throws IOException { 58 | if (valueSerializer != null) { 59 | valueSerializer.serialize(value.get(), gen, provider); 60 | } else { 61 | write(value.get(), 0, gen, provider); 62 | } 63 | } 64 | 65 | @Override 66 | public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException { 67 | TypeSerializer vts = valueTypeSerializer; 68 | if (vts != null) { 69 | vts = vts.forProperty(property); 70 | } 71 | JsonSerializer ser = valueSerializer; 72 | if (ser == null) { 73 | // A few conditions needed to be able to fetch serializer here: 74 | if (useStatic(provider, property, valueType)) { 75 | ser = provider.findTypedValueSerializer(valueType, true, property); 76 | } 77 | } else { 78 | ser = provider.handlePrimaryContextualization(ser, property); 79 | } 80 | return new LazySerializer(fullType, valueType, vts, ser); 81 | } 82 | 83 | private boolean useStatic(SerializerProvider provider, BeanProperty property, JavaType referredType) { 84 | // First: no serializer for `Object.class`, must be dynamic 85 | if (referredType.isJavaLangObject()) { 86 | return false; 87 | } 88 | // but if type is final, might as well fetch 89 | if (referredType.isFinal()) { // or should we allow annotation override? (only if requested...) 90 | return true; 91 | } 92 | // also: if indicated by typing, should be considered static 93 | if (referredType.useStaticType()) { 94 | return true; 95 | } 96 | // if neither, maybe explicit annotation? 97 | AnnotationIntrospector intr = provider.getAnnotationIntrospector(); 98 | if ((intr != null) && (property != null)) { 99 | Annotated ann = property.getMember(); 100 | if (ann != null) { 101 | JsonSerialize.Typing t = intr.findSerializationTyping(property.getMember()); 102 | if (t == JsonSerialize.Typing.STATIC) { 103 | return true; 104 | } 105 | if (t == JsonSerialize.Typing.DYNAMIC) { 106 | return false; 107 | } 108 | } 109 | } 110 | // and finally, may be forced by global static typing (unlikely...) 111 | return provider.isEnabled(MapperFeature.USE_STATIC_TYPING); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/MapSerializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.BeanProperty; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import com.fasterxml.jackson.databind.JsonMappingException; 25 | import com.fasterxml.jackson.databind.JsonSerializer; 26 | import com.fasterxml.jackson.databind.SerializerProvider; 27 | import com.fasterxml.jackson.databind.ser.ContextualSerializer; 28 | import com.fasterxml.jackson.databind.type.MapLikeType; 29 | import com.fasterxml.jackson.databind.type.TypeFactory; 30 | import io.vavr.collection.Map; 31 | 32 | import java.util.LinkedHashMap; 33 | 34 | class MapSerializer extends ValueSerializer> implements ContextualSerializer { 35 | 36 | private static final long serialVersionUID = 1L; 37 | private final MapLikeType mapType; 38 | 39 | MapSerializer(MapLikeType mapType, BeanProperty beanProperty) { 40 | super(mapType, beanProperty); 41 | this.mapType = mapType; 42 | } 43 | 44 | MapSerializer(MapLikeType mapType) { 45 | this(mapType, null); 46 | } 47 | 48 | @Override 49 | Object toJavaObj(Map value) { 50 | return value.toJavaMap(); 51 | } 52 | 53 | @Override 54 | JavaType emulatedJavaType(TypeFactory typeFactory) { 55 | return typeFactory.constructMapType(LinkedHashMap.class, mapType.getKeyType(), mapType.getContentType()); 56 | } 57 | 58 | @Override 59 | public boolean isEmpty(SerializerProvider provider, Map value) { 60 | return value.isEmpty(); 61 | } 62 | 63 | @Override 64 | public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { 65 | if (property == beanProperty) { 66 | return this; 67 | } 68 | return new MapSerializer(mapType, property); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/MultimapSerializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.BeanProperty; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import com.fasterxml.jackson.databind.JsonMappingException; 25 | import com.fasterxml.jackson.databind.JsonSerializer; 26 | import com.fasterxml.jackson.databind.SerializerProvider; 27 | import com.fasterxml.jackson.databind.ser.ContextualSerializer; 28 | import com.fasterxml.jackson.databind.type.MapLikeType; 29 | import com.fasterxml.jackson.databind.type.TypeFactory; 30 | import io.vavr.collection.Multimap; 31 | 32 | import java.util.ArrayList; 33 | import java.util.LinkedHashMap; 34 | import java.util.List; 35 | 36 | class MultimapSerializer extends ValueSerializer> implements ContextualSerializer { 37 | 38 | private static final long serialVersionUID = 1L; 39 | private final MapLikeType mapType; 40 | 41 | MultimapSerializer(MapLikeType mapType) { 42 | this(mapType, null); 43 | } 44 | 45 | MultimapSerializer(MapLikeType mapType, BeanProperty beanProperty) { 46 | super(mapType, beanProperty); 47 | this.mapType = mapType; 48 | } 49 | 50 | @Override 51 | Object toJavaObj(Multimap value) { 52 | final LinkedHashMap> result = new LinkedHashMap<>(); 53 | value.forEach(e -> result.computeIfAbsent(e._1, k -> new ArrayList<>()).add(e._2)); 54 | return result; 55 | } 56 | 57 | @Override 58 | JavaType emulatedJavaType(TypeFactory typeFactory) { 59 | JavaType containerType = typeFactory.constructCollectionType(ArrayList.class, mapType.getContentType()); 60 | return typeFactory.constructMapType(LinkedHashMap.class, mapType.getKeyType(), containerType); 61 | } 62 | 63 | @Override 64 | public boolean isEmpty(SerializerProvider provider, Multimap value) { 65 | return value.isEmpty(); 66 | } 67 | 68 | @Override 69 | public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { 70 | if (property == beanProperty) { 71 | return this; 72 | } 73 | return new MultimapSerializer(mapType, property); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/SerializableSerializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import com.fasterxml.jackson.databind.type.TypeFactory; 24 | 25 | import java.io.ByteArrayOutputStream; 26 | import java.io.IOException; 27 | import java.io.ObjectOutputStream; 28 | 29 | class SerializableSerializer extends ValueSerializer { 30 | 31 | private static final long serialVersionUID = 1L; 32 | 33 | SerializableSerializer(JavaType type) { 34 | super(type); 35 | } 36 | 37 | @Override 38 | Object toJavaObj(T value) throws IOException { 39 | ByteArrayOutputStream buf = new ByteArrayOutputStream(); 40 | ObjectOutputStream stream = new ObjectOutputStream(buf); 41 | stream.writeObject(value); 42 | return buf.toByteArray(); 43 | } 44 | 45 | @Override 46 | JavaType emulatedJavaType(TypeFactory typeFactory) { 47 | return typeFactory.constructArrayType(byte.class); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/Tuple0Serializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import io.vavr.Tuple0; 24 | 25 | import java.util.Collections; 26 | import java.util.List; 27 | 28 | class Tuple0Serializer extends TupleSerializer { 29 | 30 | Tuple0Serializer(JavaType type) { 31 | super(type); 32 | } 33 | 34 | @Override 35 | List toList(Tuple0 value) { 36 | return Collections.emptyList(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/Tuple1Serializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import io.vavr.Tuple1; 24 | 25 | import java.util.Collections; 26 | import java.util.List; 27 | 28 | class Tuple1Serializer extends TupleSerializer> { 29 | 30 | Tuple1Serializer(JavaType type) { 31 | super(type); 32 | } 33 | 34 | @Override 35 | List toList(Tuple1 value) { 36 | return Collections.singletonList(value._1); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/Tuple2Serializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import io.vavr.Tuple2; 24 | 25 | import java.util.Arrays; 26 | import java.util.List; 27 | 28 | class Tuple2Serializer extends TupleSerializer> { 29 | 30 | Tuple2Serializer(JavaType type) { 31 | super(type); 32 | } 33 | 34 | @Override 35 | List toList(Tuple2 value) { 36 | return Arrays.asList(value._1, value._2); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/Tuple3Serializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import io.vavr.Tuple3; 24 | 25 | import java.util.Arrays; 26 | import java.util.List; 27 | 28 | class Tuple3Serializer extends TupleSerializer> { 29 | 30 | Tuple3Serializer(JavaType type) { 31 | super(type); 32 | } 33 | 34 | @Override 35 | List toList(Tuple3 value) { 36 | return Arrays.asList(value._1, value._2, value._3); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/Tuple4Serializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import io.vavr.Tuple4; 24 | 25 | import java.util.Arrays; 26 | import java.util.List; 27 | 28 | class Tuple4Serializer extends TupleSerializer> { 29 | 30 | Tuple4Serializer(JavaType type) { 31 | super(type); 32 | } 33 | 34 | @Override 35 | List toList(Tuple4 value) { 36 | return Arrays.asList(value._1, value._2, value._3, value._4); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/Tuple5Serializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import io.vavr.Tuple5; 24 | 25 | import java.util.Arrays; 26 | import java.util.List; 27 | 28 | class Tuple5Serializer extends TupleSerializer> { 29 | 30 | Tuple5Serializer(JavaType type) { 31 | super(type); 32 | } 33 | 34 | @Override 35 | List toList(Tuple5 value) { 36 | return Arrays.asList(value._1, value._2, value._3, value._4, value._5); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/Tuple6Serializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import io.vavr.Tuple6; 24 | 25 | import java.util.Arrays; 26 | import java.util.List; 27 | 28 | class Tuple6Serializer extends TupleSerializer> { 29 | 30 | Tuple6Serializer(JavaType type) { 31 | super(type); 32 | } 33 | 34 | @Override 35 | List toList(Tuple6 value) { 36 | return Arrays.asList(value._1, value._2, value._3, value._4, value._5, value._6); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/Tuple7Serializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import io.vavr.Tuple7; 24 | 25 | import java.util.Arrays; 26 | import java.util.List; 27 | 28 | class Tuple7Serializer extends TupleSerializer> { 29 | 30 | Tuple7Serializer(JavaType type) { 31 | super(type); 32 | } 33 | 34 | @Override 35 | List toList(Tuple7 value) { 36 | return Arrays.asList(value._1, value._2, value._3, value._4, value._5, value._6, value._7); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/Tuple8Serializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.databind.JavaType; 23 | import io.vavr.Tuple8; 24 | 25 | import java.util.Arrays; 26 | import java.util.List; 27 | 28 | class Tuple8Serializer extends TupleSerializer> { 29 | 30 | Tuple8Serializer(JavaType type) { 31 | super(type); 32 | } 33 | 34 | @Override 35 | List toList(Tuple8 value) { 36 | return Arrays.asList(value._1, value._2, value._3, value._4, value._5, value._6, value._7, value._8); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/TupleSerializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.core.JsonGenerator; 23 | import com.fasterxml.jackson.databind.JavaType; 24 | import com.fasterxml.jackson.databind.SerializerProvider; 25 | 26 | import java.io.IOException; 27 | import java.util.List; 28 | 29 | abstract class TupleSerializer extends HListSerializer { 30 | 31 | private static final long serialVersionUID = 1L; 32 | 33 | TupleSerializer(JavaType type) { 34 | super(type); 35 | } 36 | 37 | @Override 38 | public void serialize(T value, JsonGenerator gen, SerializerProvider provider) throws IOException { 39 | gen.writeStartArray(); 40 | List list = toList(value); 41 | for (int i = 0; i < list.size(); i++) { 42 | write(list.get(i), i, gen, provider); 43 | } 44 | gen.writeEndArray(); 45 | } 46 | 47 | abstract List toList(T value); 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/UnwrappingOptionSerializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.core.JsonGenerationException; 23 | import com.fasterxml.jackson.core.JsonGenerator; 24 | import com.fasterxml.jackson.databind.*; 25 | import com.fasterxml.jackson.databind.ser.BeanSerializer; 26 | import com.fasterxml.jackson.databind.ser.ContextualSerializer; 27 | import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase; 28 | import com.fasterxml.jackson.databind.ser.std.StdSerializer; 29 | import com.fasterxml.jackson.databind.util.NameTransformer; 30 | import io.vavr.control.Either; 31 | import io.vavr.control.Option; 32 | 33 | import java.io.IOException; 34 | 35 | /** 36 | * Serializer for {@link Option} that unwraps the value if it is defined and the property is annotated with {@code @JsonUnwrapped}. 37 | * 38 | * Note that {@code Option} values of other Vavr types like {@link io.vavr.control.Try}, {@link Either}, etc are not supported 39 | * due to {@link com.fasterxml.jackson.annotation.JsonUnwrapped} only supports Java beans. 40 | * 41 | * Delegates the unwrapping to a {@link com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer} 42 | * since to support unwrapping requires to serialize only the fields instead of the whole object 43 | * but that is an internal {@link BeanSerializerBase} function and therefore not available here. 44 | */ 45 | class UnwrappingOptionSerializer extends StdSerializer> implements ContextualSerializer { 46 | 47 | private static final long serialVersionUID = 1L; 48 | private final OptionSerializer optionSerializer; 49 | private final NameTransformer unwrapper; 50 | 51 | public UnwrappingOptionSerializer(OptionSerializer optionSerializer, NameTransformer unwrapper) { 52 | super(optionSerializer.getValueType()); 53 | this.optionSerializer = optionSerializer; 54 | this.unwrapper = unwrapper; 55 | } 56 | 57 | /** 58 | * Try to serialize the option value. 59 | * Writes null if the value is not defined. 60 | * 61 | * @param value Value to serialize; can not be null. 62 | * @param gen Generator used to output resulting Json content 63 | * @param provider Provider that can be used to get serializers for serializing Objects value contains, if any. 64 | * @throws JsonGenerationException if the option value is not a bean 65 | */ 66 | @Override 67 | public void serialize(Option value, JsonGenerator gen, SerializerProvider provider) throws IOException { 68 | if (value.isDefined()) { 69 | JsonSerializer ser; 70 | Object val = value.get(); 71 | JavaType containedType = optionSerializer.getValueType().containedType(0); 72 | if (containedType != null && containedType.hasGenericTypes()) { 73 | JavaType st = provider.constructSpecializedType(containedType, val.getClass()); 74 | ser = provider.findTypedValueSerializer(st, true, null); 75 | } else { 76 | ser = provider.findTypedValueSerializer(val.getClass(), true, null); 77 | } 78 | // can only unwrap if the inner values is a bean. 79 | if (ser instanceof BeanSerializer) { 80 | JsonSerializer unwrappingSerializer = ser.unwrappingSerializer(unwrapper); 81 | unwrappingSerializer.serialize(val, gen, provider); 82 | } else { 83 | // Cannot unwrap a non-bean object, so throw an exception 84 | throw new JsonGenerationException("Cannot unwrap a non-bean object", gen); 85 | } 86 | } else { 87 | gen.writeNull(); 88 | } 89 | } 90 | 91 | @Override 92 | public boolean isUnwrappingSerializer() { 93 | return true; // sure it is 94 | } 95 | 96 | @Override 97 | public boolean isEmpty(SerializerProvider provider, Option value) { 98 | return value.isEmpty(); 99 | } 100 | 101 | @Override 102 | public JsonSerializer createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException { 103 | return optionSerializer.createContextual(provider, property); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/io/vavr/jackson/datatype/serialize/ValueSerializer.java: -------------------------------------------------------------------------------- 1 | /* __ __ __ __ __ ___ 2 | * \ \ / / \ \ / / __/ 3 | * \ \/ / /\ \ \/ / / 4 | * \____/__/ \__\____/__/ 5 | * 6 | * Copyright 2014-2025 Vavr, http://vavr.io 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package io.vavr.jackson.datatype.serialize; 21 | 22 | import com.fasterxml.jackson.core.JsonGenerator; 23 | import com.fasterxml.jackson.core.JsonToken; 24 | import com.fasterxml.jackson.databind.BeanProperty; 25 | import com.fasterxml.jackson.databind.JavaType; 26 | import com.fasterxml.jackson.databind.JsonSerializer; 27 | import com.fasterxml.jackson.databind.SerializerProvider; 28 | import com.fasterxml.jackson.databind.jsontype.TypeSerializer; 29 | import com.fasterxml.jackson.databind.ser.std.StdSerializer; 30 | import com.fasterxml.jackson.databind.type.TypeFactory; 31 | 32 | import java.io.IOException; 33 | 34 | abstract class ValueSerializer extends StdSerializer { 35 | 36 | private static final long serialVersionUID = 1L; 37 | 38 | final JavaType type; 39 | final BeanProperty beanProperty; 40 | 41 | ValueSerializer(JavaType type) { 42 | this(type, null); 43 | } 44 | 45 | ValueSerializer(JavaType type, BeanProperty property) { 46 | super(type); 47 | this.type = type; 48 | this.beanProperty = property; 49 | } 50 | 51 | abstract Object toJavaObj(T value) throws IOException; 52 | 53 | abstract JavaType emulatedJavaType(TypeFactory typeFactory); 54 | 55 | @Override 56 | public void serialize(T value, JsonGenerator gen, SerializerProvider provider) throws IOException { 57 | Object obj = toJavaObj(value); 58 | if (obj == null) { 59 | provider.getDefaultNullValueSerializer().serialize(null, gen, provider); 60 | } else { 61 | JsonSerializer ser; 62 | try { 63 | JavaType emulated = emulatedJavaType(provider.getTypeFactory()); 64 | if (emulated.getRawClass() != Object.class) { 65 | ser = provider.findTypedValueSerializer(emulated, true, beanProperty); 66 | } else { 67 | ser = provider.findTypedValueSerializer(obj.getClass(), true, beanProperty); 68 | } 69 | } catch (Exception ignore) { 70 | ser = provider.findTypedValueSerializer(obj.getClass(), true, beanProperty); 71 | } 72 | ser.serialize(obj, gen, provider); 73 | } 74 | } 75 | 76 | @Override 77 | public void serializeWithType(T value, JsonGenerator gen, SerializerProvider serializers, 78 | TypeSerializer typeSer) throws IOException { 79 | typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.VALUE_STRING)); 80 | serialize(value, gen, serializers); 81 | typeSer.writeTypeSuffix(gen, typeSer.typeId(value, JsonToken.VALUE_STRING)); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module: -------------------------------------------------------------------------------- 1 | # __ __ __ __ __ ___ 2 | # \ \ / / \ \ / / __/ 3 | # \ \/ / /\ \ \/ / / 4 | # \____/__/ \__\____/__/ 5 | # 6 | # Copyright 2014-2025 Vavr, http://vavr.io 7 | # 8 | # Licensed under the Apache License, Version 2.0 (the "License"); 9 | # you may not use this file except in compliance with the License. 10 | # You may obtain a copy of the License at 11 | # 12 | # http://www.apache.org/licenses/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing, software 15 | # distributed under the License is distributed on an "AS IS" BASIS, 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | io.vavr.jackson.datatype.VavrModule 20 | -------------------------------------------------------------------------------- /src/test/java/generator/SimplePojo.java: -------------------------------------------------------------------------------- 1 | package generator; 2 | 3 | import com.squareup.javapoet.ClassName; 4 | import com.squareup.javapoet.JavaFile; 5 | import com.squareup.javapoet.MethodSpec; 6 | import com.squareup.javapoet.TypeName; 7 | import com.squareup.javapoet.TypeSpec; 8 | import io.vavr.collection.PriorityQueue; 9 | import org.junit.jupiter.api.Assertions; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import javax.lang.model.element.Modifier; 13 | import java.io.File; 14 | import java.io.IOException; 15 | 16 | import static generator.utils.Initializer.initMapper; 17 | import static generator.utils.Initializer.initValue; 18 | import static generator.utils.PoetHelpers.simplePojo; 19 | import static generator.utils.Serializer.expectedJson; 20 | 21 | /** 22 | * @author Ruslan Sennov 23 | */ 24 | public class SimplePojo { 25 | 26 | public static void main(String[] args) throws IOException { 27 | java.util.Map cases = new java.util.HashMap<>(); 28 | cases.put("PriorityQueueOfString", PriorityQueue.of("A", "B")); 29 | generate(cases); 30 | } 31 | 32 | static void generate(java.util.Map cases) throws IOException { 33 | 34 | TypeSpec.Builder pojoTest = TypeSpec.classBuilder("SimplePojoTest") 35 | .addJavadoc("generated\n") 36 | .addModifiers(Modifier.PUBLIC); 37 | initMapper(pojoTest, "MAPPER"); 38 | 39 | cases.forEach((k, v) -> addCase(pojoTest, k, v)); 40 | 41 | JavaFile javaFile = JavaFile.builder("io.vavr.jackson.generated", pojoTest.build()) 42 | .indent(" ") 43 | .skipJavaLangImports(true) 44 | .build(); 45 | 46 | javaFile.writeTo(new File("src/test/java")); 47 | } 48 | 49 | private static void addCase(TypeSpec.Builder builder, String pojoName, Object value) { 50 | addCase(builder, pojoName, value, 0); 51 | } 52 | 53 | private static void addCase(TypeSpec.Builder builder, String pojoName, Object value, int opts) { 54 | 55 | MethodSpec.Builder testBuilder = MethodSpec.methodBuilder("test" + pojoName) 56 | .addAnnotation(Test.class) 57 | .addException(ClassName.get(Exception.class)); 58 | TypeName valueTypeName = initValue(testBuilder, "src", value); 59 | MethodSpec testSpec = testBuilder 60 | .addStatement("$T json = MAPPER.writeValueAsString(new $L().setValue(src))", ClassName.get(String.class), pojoName) 61 | .addStatement("$T.assertEquals(json, $S)", ClassName.get(Assertions.class), "{\"value\":" + expectedJson(value, opts) + "}") 62 | .addStatement("$L restored = MAPPER.readValue(json, $L.class)", pojoName, pojoName) 63 | .addStatement("$T.assertEquals(src, restored.getValue())", ClassName.get(Assertions.class)) 64 | .build(); 65 | builder.addMethod(testSpec); 66 | builder.addType(simplePojo(pojoName, valueTypeName)); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/generator/utils/PoetHelpers.java: -------------------------------------------------------------------------------- 1 | package generator.utils; 2 | 3 | import com.squareup.javapoet.ClassName; 4 | import com.squareup.javapoet.FieldSpec; 5 | import com.squareup.javapoet.MethodSpec; 6 | import com.squareup.javapoet.ParameterSpec; 7 | import com.squareup.javapoet.TypeName; 8 | import com.squareup.javapoet.TypeSpec; 9 | 10 | import javax.lang.model.element.Modifier; 11 | 12 | /** 13 | * @author Ruslan Sennov 14 | */ 15 | public class PoetHelpers { 16 | 17 | public static TypeSpec simplePojo(String pojoName, TypeName valueTypeName) { 18 | return TypeSpec.classBuilder(pojoName) 19 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC) 20 | .addField(FieldSpec.builder(valueTypeName, "v", Modifier.PRIVATE).build()) 21 | .addMethod(MethodSpec.methodBuilder("getValue") 22 | .addModifiers(Modifier.PUBLIC) 23 | .returns(valueTypeName) 24 | .addStatement("return v") 25 | .build()) 26 | .addMethod(MethodSpec.methodBuilder("setValue") 27 | .addModifiers(Modifier.PUBLIC) 28 | .returns(ClassName.get("", pojoName)) 29 | .addParameter(ParameterSpec.builder(valueTypeName, "v").build()) 30 | .addStatement("this.v = v") 31 | .addStatement("return this") 32 | .build()) 33 | .build(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/CharSeqTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype; 2 | 3 | import com.fasterxml.jackson.databind.JsonMappingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.fasterxml.jackson.databind.ObjectWriter; 6 | import io.vavr.collection.CharSeq; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.io.IOException; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; 13 | 14 | class CharSeqTest extends BaseTest { 15 | 16 | @Test 17 | void shouldSerializeAndDeserializeCharSeq() throws IOException { 18 | ObjectWriter writer = mapper().writer(); 19 | CharSeq src = CharSeq.of("abc"); 20 | String json = writer.writeValueAsString(src); 21 | assertThat(json).isEqualTo("\"abc\""); 22 | CharSeq dst = mapper().readValue(json, CharSeq.class); 23 | assertThat((Iterable) dst).isEqualTo(src); 24 | } 25 | 26 | @Test 27 | void shouldSerializeAndDeserializeWrappedCharSeqAsObject() throws IOException { 28 | ObjectMapper mapper = mapper().addMixIn(CharSeq.class, WrapperObject.class); 29 | CharSeq src = CharSeq.of("abc"); 30 | String plainJson = mapper().writeValueAsString(src); 31 | String wrappedJson = mapper.writeValueAsString(src); 32 | assertThat(wrapToObject(CharSeq.class.getName(), plainJson)).isEqualTo(wrappedJson); 33 | CharSeq restored = mapper.readValue(wrappedJson, CharSeq.class); 34 | assertThat((Iterable) restored).isEqualTo(src); 35 | } 36 | 37 | @Test 38 | void shouldSerializeAndDeserializeWrappedCharSeqAsArray() throws IOException { 39 | ObjectMapper mapper = mapper().addMixIn(CharSeq.class, WrapperArray.class); 40 | CharSeq src = CharSeq.of("abc"); 41 | String plainJson = mapper().writeValueAsString(src); 42 | String wrappedJson = mapper.writeValueAsString(src); 43 | assertThat(wrapToArray(CharSeq.class.getName(), plainJson)).isEqualTo(wrappedJson); 44 | CharSeq restored = mapper.readValue(wrappedJson, CharSeq.class); 45 | assertThat((Iterable) restored).isEqualTo(src); 46 | } 47 | 48 | @Test 49 | void shouldThrowExceptionWhenDeserializingInvalidCharSeq() { 50 | assertThatExceptionOfType(JsonMappingException.class).isThrownBy(() -> mapper().readValue("42", CharSeq.class)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/MixedTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import com.fasterxml.jackson.databind.JsonMappingException; 5 | import io.vavr.collection.HashMap; 6 | import io.vavr.collection.List; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.io.IOException; 10 | import java.util.Arrays; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; 14 | 15 | class MixedTest extends BaseTest { 16 | 17 | @Test 18 | void shouldSerializeAndDeserializeVavrHashMapWithListValues() throws IOException { 19 | Object src = HashMap.empty().put("key1", List.of(1, 2)).put("key2", List.of(3, 4)); 20 | String json = mapper().writer().writeValueAsString(src); 21 | assertThat(src).isEqualTo(mapper().readValue(json, new TypeReference>>() { 22 | })); 23 | } 24 | 25 | @Test 26 | void shouldSerializeAndDeserializeListOfVavrHashMaps() throws IOException { 27 | Object src = List.of(HashMap.empty().put("key1", 1), HashMap.empty().put("key2", 2)); 28 | String json = mapper().writer().writeValueAsString(src); 29 | assertThat(src).isEqualTo(mapper().readValue(json, new TypeReference>>() { 30 | })); 31 | } 32 | 33 | @Test 34 | void shouldSerializeAndDeserializeListContainingJavaMap() throws IOException { 35 | java.util.Map javaHMap = new java.util.HashMap<>(); 36 | javaHMap.put("1", "2"); 37 | List src = List.of(javaHMap); 38 | List restored = mapper().readValue(mapper().writer().writeValueAsString(src), List.class); 39 | assertThat(src).isEqualTo(restored); 40 | } 41 | 42 | @Test 43 | void shouldThrowJsonMappingExceptionForInvalidListElements() { 44 | assertThatExceptionOfType(JsonMappingException.class).isThrownBy(() -> 45 | mapper().readValue("[\"s\"]", new TypeReference>() { 46 | })); 47 | } 48 | 49 | @Test 50 | void shouldSerializeAndDeserializeNestedVavrLists() throws IOException { 51 | Object src = List.of(List.of(1)); 52 | String json = mapper().writer().writeValueAsString(src); 53 | assertThat(src).isEqualTo(mapper().readValue(json, new TypeReference>>() { 54 | })); 55 | } 56 | 57 | @Test 58 | void shouldSerializeAndDeserializeVavrHashMapWithNestedHashMapValues() throws IOException { 59 | Object src = HashMap.empty().put("1", HashMap.empty().put("X", "Y")); 60 | String json = mapper().writer().writeValueAsString(src); 61 | assertThat(src).isEqualTo(mapper().readValue(json, new TypeReference>>() { 62 | })); 63 | } 64 | 65 | @Test 66 | void shouldSerializeAndDeserializeListContainingJavaList() throws IOException { 67 | Object src = List.of(Arrays.asList(1, 2)); 68 | String json = mapper().writer().writeValueAsString(src); 69 | assertThat(src).isEqualTo(mapper().readValue(json, List.class)); 70 | assertThat(src).isEqualTo(mapper().readValue(json, new TypeReference>>() { 71 | })); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/OptionJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.control.Option; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | class OptionJsonMergeTest extends BaseTest { 11 | static class TestJsonMergeWithString { 12 | @JsonMerge(OptBoolean.TRUE) 13 | public Option value = Option.of("default"); 14 | } 15 | 16 | static class TestJsonMergeWithPojo { 17 | @JsonMerge(OptBoolean.TRUE) 18 | public final Option value; 19 | 20 | protected TestJsonMergeWithPojo() { 21 | value = Option.of(new POJO(7, 2)); 22 | } 23 | 24 | public TestJsonMergeWithPojo(int x, int y) { 25 | value = Option.of(new POJO(x, y)); 26 | } 27 | } 28 | 29 | static class POJO { 30 | public int x, y; 31 | 32 | protected POJO() { 33 | } 34 | 35 | public POJO(int x, int y) { 36 | this.x = x; 37 | this.y = y; 38 | } 39 | } 40 | 41 | @Test 42 | void shouldMergeString() throws Exception { 43 | TestJsonMergeWithString result = mapper().readValue(asJson("{'value':'override'}"), TestJsonMergeWithString.class); 44 | 45 | assertThat(result.value.get()).isEqualTo("override"); 46 | } 47 | 48 | @Test 49 | void shouldMergePojo() throws Exception { 50 | TestJsonMergeWithPojo result = mapper().readValue(asJson("{'value':{'y':-6}}"), TestJsonMergeWithPojo.class); 51 | assertThat(result.value.get().x).isEqualTo(7); 52 | assertThat(result.value.get().y).isEqualTo(-6); 53 | } 54 | 55 | @Test 56 | void shouldMergeWhileRetainingValues() throws Exception { 57 | TestJsonMergeWithPojo result = mapper().readerForUpdating(new TestJsonMergeWithPojo(10, 20)) 58 | .readValue(asJson("{'value':{'x':11}}")); 59 | 60 | assertThat(result.value.get().x).isEqualTo(11); 61 | assertThat(result.value.get().y).isEqualTo(20); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/OptionPlainTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype; 2 | 3 | import io.vavr.control.Option; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.io.IOException; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | class OptionPlainTest extends BaseTest { 11 | 12 | @Test 13 | void shouldSerializeAndDeserializeDefinedOptionPlainValue() throws IOException { 14 | Option src = Option.of(1); 15 | String json = mapper().writer().writeValueAsString(src); 16 | assertThat(json).isEqualTo("1"); 17 | Option restored = mapper().readValue(json, Option.class); 18 | assertThat(restored).isEqualTo(src); 19 | } 20 | 21 | @Test 22 | void shouldSerializeAndDeserializeNoneOptionPlainValue() throws IOException { 23 | Option src = Option.none(); 24 | String json = mapper().writer().writeValueAsString(src); 25 | assertThat(json).isEqualTo("null"); 26 | Option restored = mapper().readValue(json, Option.class); 27 | assertThat(restored).isEqualTo(src); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/ScalarTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import com.fasterxml.jackson.databind.DeserializationFeature; 5 | import io.vavr.collection.List; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.io.IOException; 9 | import java.math.BigDecimal; 10 | import java.math.BigInteger; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | class ScalarTest extends BaseTest { 15 | 16 | @Test 17 | void shouldDeserializeIntegerList() throws IOException { 18 | List l1 = mapper().readValue("[1]", new TypeReference>() { 19 | }); 20 | assertThat(List.of(1)).isEqualTo(l1); 21 | } 22 | 23 | @Test 24 | void shouldDeserializeBooleanList() throws IOException { 25 | List l2 = mapper().readValue("[true]", new TypeReference>() { 26 | }); 27 | assertThat(List.of(true)).isEqualTo(l2); 28 | 29 | List l3 = mapper().readValue("[false]", new TypeReference>() { 30 | }); 31 | assertThat(List.of(false)).isEqualTo(l3); 32 | } 33 | 34 | @Test 35 | void shouldDeserializeFloatList() throws IOException { 36 | List l4 = mapper().readValue("[2.4]", new TypeReference>() { 37 | }); 38 | assertThat(List.of(2.4f)).isEqualTo(l4); 39 | } 40 | 41 | @Test 42 | void shouldDeserializeDoubleAndBigDecimalList() throws IOException { 43 | List l5 = mapper().readValue("[2.4]", new TypeReference>() { 44 | }); 45 | assertThat(List.of(2.4)).isEqualTo(l5); 46 | 47 | List l5d = mapper().enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) 48 | .readValue("[2.4]", new TypeReference>() { 49 | }); 50 | assertThat(List.of(BigDecimal.valueOf(2.4))).isEqualTo(l5d); 51 | } 52 | 53 | @Test 54 | void shouldDeserializeStringList() throws IOException { 55 | List l6 = mapper().readValue("[\"1\"]", new TypeReference>() { 56 | }); 57 | assertThat(List.of("1")).isEqualTo(l6); 58 | } 59 | 60 | @Test 61 | void shouldDeserializeLongList() throws IOException { 62 | List l7 = mapper().readValue("[24]", new TypeReference>() { 63 | }); 64 | assertThat(List.of(24L)).isEqualTo(l7); 65 | 66 | List l8 = mapper().readValue("[" + Long.MAX_VALUE + "]", new TypeReference>() { 67 | }); 68 | assertThat(List.of(Long.MAX_VALUE)).isEqualTo(l8); 69 | } 70 | 71 | @Test 72 | void shouldDeserializeBigIntegerList() throws IOException { 73 | List l9 = mapper().readValue("[1234567890123456789012]", new TypeReference>() { 74 | }); 75 | assertThat(List.of(new BigInteger("1234567890123456789012"))).isEqualTo(l9); 76 | } 77 | 78 | @Test 79 | void shouldDeserializeFloatToIntegerList() throws IOException { 80 | assertThat(List.of(1)).isEqualTo(mapper().readValue("[1.3]", new TypeReference>() { 81 | })); 82 | } 83 | 84 | @Test 85 | void shouldDeserializeIntegerToStringList() throws IOException { 86 | assertThat(List.of("1")).isEqualTo(mapper().readValue("[1]", new TypeReference>() { 87 | })); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/SerializationFeatureTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import com.fasterxml.jackson.databind.ObjectWriter; 5 | import com.fasterxml.jackson.databind.SerializationFeature; 6 | import com.fasterxml.jackson.dataformat.csv.CsvMapper; 7 | import com.fasterxml.jackson.datatype.joda.JodaModule; 8 | import io.vavr.collection.List; 9 | import org.joda.time.DateTime; 10 | import org.joda.time.DateTimeZone; 11 | import org.junit.jupiter.api.Test; 12 | 13 | import java.io.IOException; 14 | import java.util.ArrayList; 15 | 16 | import static org.assertj.core.api.Assertions.assertThat; 17 | 18 | class SerializationFeatureTest { 19 | 20 | @Test 21 | void shouldApplySerializationFeatureListDateTime() throws IOException { 22 | DateTime dateTime = new DateTime(2016, 6, 6, 8, 0, DateTimeZone.forID("CET")); 23 | io.vavr.collection.List dateTimeList = List.of(dateTime); 24 | java.util.List dateTimeJavaList = new ArrayList<>(); 25 | dateTimeJavaList.add(dateTime); 26 | 27 | CsvMapper mapper = new CsvMapper(); 28 | mapper.registerModule(new JodaModule()); 29 | mapper.registerModule(new VavrModule()); 30 | ObjectWriter writer = mapper.writer().without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 31 | 32 | String serializedDateTime = writer.writeValueAsString(dateTime); 33 | String serializedDateTimeJavaList = writer.writeValueAsString(dateTimeJavaList); 34 | String serializedDateTimeList = writer.writeValueAsString(dateTimeList); 35 | 36 | assertThat(serializedDateTimeJavaList).isEqualTo(serializedDateTime); 37 | assertThat(serializedDateTimeList).isEqualTo(serializedDateTimeJavaList); 38 | 39 | List restored = mapper.readValue(serializedDateTimeList, new TypeReference>() { 40 | }); 41 | assertThat(dateTime.getMillis()).isEqualTo(restored.head().getMillis()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/ServiceLoaderTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import io.vavr.Lazy; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | class ServiceLoaderTest { 10 | 11 | /** 12 | * Since there is no way (without reflection) to interrogate the mapper to see which modules 13 | * are loaded, we can do so indirectly by simply asking it to handle any vavr type. 14 | * Non-failure means success 15 | * 16 | * @throws Exception only if jackson fails to handle vavr types - meaning auto-register didn't work 17 | */ 18 | @Test 19 | void shouldAutoDiscover() throws Exception { 20 | ObjectMapper mapper = new ObjectMapper().findAndRegisterModules(); 21 | 22 | Lazy src = Lazy.of(() -> 1); 23 | String json = mapper.writer().writeValueAsString(src); 24 | assertThat(json).isEqualTo("1"); 25 | Lazy restored = mapper.readValue(json, Lazy.class); 26 | assertThat(restored).isEqualTo(src); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/bean/BeanAnnotationTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.bean; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import io.vavr.collection.CharSeq; 5 | import io.vavr.collection.HashMap; 6 | import io.vavr.collection.HashMultimap; 7 | import io.vavr.collection.HashSet; 8 | import io.vavr.collection.List; 9 | import io.vavr.collection.Map; 10 | import io.vavr.collection.Multimap; 11 | import io.vavr.collection.Seq; 12 | import io.vavr.collection.Set; 13 | import io.vavr.control.Either; 14 | import io.vavr.control.Option; 15 | import io.vavr.jackson.datatype.BaseTest; 16 | import org.junit.jupiter.api.Test; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | public class BeanAnnotationTest extends BaseTest { 21 | 22 | public static final String CHARSEQ_VALUE = "CHARSEQ_VALUE"; 23 | public static final String EITHER_VALUE = "EITHER_VALUE"; 24 | public static final String MAP_VALUE = "MAP_VALUE"; 25 | public static final String MULTIMAP_VALUE = "MULTIMAP_VALUE"; 26 | public static final String OPTION_VALUE = "OPTION_VALUE"; 27 | public static final String SEQ_VALUE = "SEQ_VALUE"; 28 | public static final String SET_VALUE = "SET_VALUE"; 29 | public static final String EMPTY_JSON = "{}"; 30 | 31 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 32 | static class BeanObjectOptional { 33 | 34 | public CharSeq charSeq; 35 | public Either either; 36 | public Map map; 37 | public Multimap multimap; 38 | public Option option; 39 | public Seq seq; 40 | public Set set; 41 | 42 | public BeanObjectOptional() { 43 | this(true); 44 | } 45 | 46 | public BeanObjectOptional(boolean empty) { 47 | if (empty) { 48 | charSeq = CharSeq.empty(); 49 | either = Either.left(EITHER_VALUE); 50 | option = Option.none(); 51 | map = HashMap.empty(); 52 | multimap = HashMultimap.withSeq().empty(); 53 | seq = List.empty(); 54 | set = HashSet.empty(); 55 | } else { 56 | charSeq = CharSeq.of(CHARSEQ_VALUE); 57 | either = Either.right(EITHER_VALUE); 58 | option = Option.of(OPTION_VALUE); 59 | map = HashMap.of("key", MAP_VALUE); 60 | multimap = HashMultimap.withSeq().of("key", MULTIMAP_VALUE); 61 | seq = List.of(SEQ_VALUE); 62 | set = HashSet.of(SET_VALUE); 63 | } 64 | } 65 | } 66 | 67 | @Test 68 | void nonEmpty() throws Exception { 69 | BeanObjectOptional bean = new BeanObjectOptional(false); 70 | String json = mapper().writer().writeValueAsString(bean); 71 | assertThat(json.contains(CHARSEQ_VALUE)).isTrue(); 72 | assertThat(json.contains(EITHER_VALUE)).isTrue(); 73 | assertThat(json.contains(OPTION_VALUE)).isTrue(); 74 | assertThat(json.contains(MAP_VALUE)).isTrue(); 75 | assertThat(json.contains(MULTIMAP_VALUE)).isTrue(); 76 | assertThat(json.contains(SEQ_VALUE)).isTrue(); 77 | assertThat(json.contains(SET_VALUE)).isTrue(); 78 | } 79 | 80 | @Test 81 | void empty() throws Exception { 82 | BeanObjectOptional bean = new BeanObjectOptional(); 83 | String json = mapper().writer().writeValueAsString(bean); 84 | assertThat(json).isEqualTo(EMPTY_JSON); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/bean/ComplexBeanTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.bean; 2 | 3 | import io.vavr.jackson.datatype.BaseTest; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.io.IOException; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | class ComplexBeanTest extends BaseTest { 11 | 12 | @Test 13 | void test1() throws IOException { 14 | 15 | final ComplexClass src = ComplexClass.build(); 16 | final String json = mapper().writer().writeValueAsString(src); 17 | final ComplexClass fromJson = mapper().readValue(json, ComplexClass.class); 18 | 19 | assertThat(src.getComplexInnerClasses()).isEqualTo(fromJson.getComplexInnerClasses()); 20 | assertThat(src.getComplexInnerClassHashSet()).isEqualTo(fromJson.getComplexInnerClassHashSet()); 21 | assertThat(src.getComplexInnerClassList()).isEqualTo(fromJson.getComplexInnerClassList()); 22 | assertThat(src.getComplexInnerClassQueue()).isEqualTo(fromJson.getComplexInnerClassQueue()); 23 | assertThat(src.getComplexInnerClassStream()).isEqualTo(fromJson.getComplexInnerClassStream()); 24 | assertThat(src.getComplexInnerClassVector()).isEqualTo(fromJson.getComplexInnerClassVector()); 25 | assertThat(src.getComplexInnerClassTuple2()).isEqualTo(fromJson.getComplexInnerClassTuple2()); 26 | assertThat(src.getComplexInnerClassTreeMap()).isEqualTo(fromJson.getComplexInnerClassTreeMap()); 27 | assertThat(src.getComplexInnerClassHashMap()).isEqualTo(fromJson.getComplexInnerClassHashMap()); 28 | assertThat(src.getComplexInnerClassTreeMultimap()).isEqualTo(fromJson.getComplexInnerClassTreeMultimap()); 29 | assertThat(src.getComplexInnerClassHashMultimap()).isEqualTo(fromJson.getComplexInnerClassHashMultimap()); 30 | assertThat(src.getOpt1()).isEqualTo(fromJson.getOpt1()); 31 | assertThat(src.getOpt2()).isEqualTo(fromJson.getOpt2()); 32 | assertThat(src.getComplexInnerClassTreeSet()).isEqualTo(fromJson.getComplexInnerClassTreeSet()); 33 | 34 | final ComplexClass.ComplexInnerClass srcInnerClassFromTuple2 = src.getComplexInnerClassTuple2()._2; 35 | final ComplexClass.ComplexInnerClass fromJsonInnerClassFromTuple2 = fromJson.getComplexInnerClassTuple2()._2; 36 | assertThat(fromJsonInnerClassFromTuple2).isEqualTo(srcInnerClassFromTuple2); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/docs/ReadmeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.docs; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import io.vavr.collection.List; 6 | import io.vavr.jackson.datatype.BaseTest; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class ReadmeTest extends BaseTest { 12 | 13 | @Test 14 | void deser() throws Exception { 15 | ObjectMapper mapper = mapper(); 16 | 17 | // readme: Serialization/deserialization 18 | String json = mapper.writeValueAsString(List.of(1)); 19 | List restored = mapper.readValue(json, new TypeReference>() { 20 | }); 21 | // end of readme 22 | 23 | assertThat(json).isEqualTo("[1]"); 24 | assertThat(restored).isEqualTo(List.of(1)); 25 | assertThat(restored.toString()).isEqualTo("List(1)"); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/map/HashMapJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.map; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import io.vavr.Tuple; 7 | import io.vavr.collection.HashMap; 8 | import io.vavr.jackson.datatype.BaseTest; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | class HashMapJsonMergeTest extends BaseTest { 14 | 15 | static class TestJsonMergeWithHashMap { 16 | @JsonMerge(OptBoolean.TRUE) 17 | public HashMap value = HashMap.of("foo1", "bar1"); 18 | } 19 | 20 | static class TestJsonMergeWithNestedMap { 21 | @JsonMerge(OptBoolean.TRUE) 22 | public HashMap> value = HashMap.of("foo1", HashMap.of("foo_nested", "bar_nested")); 23 | } 24 | 25 | @Test 26 | void shouldMergeString() throws Exception { 27 | TestJsonMergeWithHashMap result = mapper().readValue(asJson("{'value': {'foo2':'bar2'}}"), TestJsonMergeWithHashMap.class); 28 | 29 | assertThat(result.value) 30 | .hasSize(2) 31 | .containsExactly( 32 | Tuple.of("foo1", "bar1"), 33 | Tuple.of("foo2", "bar2")); 34 | } 35 | 36 | @Test 37 | void shouldMergeNested() throws JsonProcessingException { 38 | TestJsonMergeWithNestedMap result = mapper().readValue(asJson("{'value': {'foo1': {'foo_nested2': 'bar_nested2'}}}"), TestJsonMergeWithNestedMap.class); 39 | 40 | assertThat(result.value) 41 | .hasSize(1) 42 | .containsExactly(Tuple.of("foo1", HashMap.of( 43 | "foo_nested", "bar_nested", 44 | "foo_nested2", "bar_nested2"))); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/map/HashMapTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.map; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.collection.HashMap; 5 | import io.vavr.collection.Map; 6 | import io.vavr.control.Option; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.io.IOException; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | class HashMapTest extends MapTest { 14 | @Override 15 | Class clz() { 16 | return HashMap.class; 17 | } 18 | 19 | @Override 20 | Map emptyMap() { 21 | return HashMap.empty(); 22 | } 23 | 24 | @Override 25 | protected TypeReference>> typeReferenceWithOption() { 26 | return new TypeReference>>() { 27 | }; 28 | } 29 | 30 | @Test 31 | void defaultDeserialization() throws IOException { 32 | assertThat(HashMap.empty().put("1", "2")).isEqualTo(mapper().readValue("{\"1\":\"2\"}", Map.class)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/map/LinkedHashMapJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.map; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import io.vavr.Tuple; 7 | import io.vavr.collection.LinkedHashMap; 8 | import io.vavr.jackson.datatype.BaseTest; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | class LinkedHashMapJsonMergeTest extends BaseTest { 14 | 15 | static class TestJsonMergeWithLinkedHashMap { 16 | @JsonMerge(OptBoolean.TRUE) 17 | public LinkedHashMap value = LinkedHashMap.of("foo1", "bar1"); 18 | } 19 | 20 | static class TestJsonMergeWithNestedMap { 21 | @JsonMerge(OptBoolean.TRUE) 22 | public LinkedHashMap> value = LinkedHashMap.of("foo1", LinkedHashMap.of("foo_nested", "bar_nested")); 23 | } 24 | 25 | @Test 26 | void shouldMergeString() throws Exception { 27 | TestJsonMergeWithLinkedHashMap result = mapper().readValue(asJson("{'value': {'foo2':'bar2'}}"), TestJsonMergeWithLinkedHashMap.class); 28 | 29 | assertThat(result.value) 30 | .hasSize(2) 31 | .containsExactly( 32 | Tuple.of("foo1", "bar1"), 33 | Tuple.of("foo2", "bar2")); 34 | } 35 | 36 | @Test 37 | void shouldMergeNested() throws JsonProcessingException { 38 | TestJsonMergeWithNestedMap result = mapper().readValue(asJson("{'value': {'foo1': {'foo_nested2': 'bar_nested2'}}}"), TestJsonMergeWithNestedMap.class); 39 | 40 | assertThat(result.value) 41 | .hasSize(1) 42 | .containsExactly(Tuple.of("foo1", LinkedHashMap.of( 43 | "foo_nested", "bar_nested", 44 | "foo_nested2", "bar_nested2"))); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/map/LinkedHashMapTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.map; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.collection.LinkedHashMap; 5 | import io.vavr.collection.Map; 6 | import io.vavr.control.Option; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.io.IOException; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | class LinkedHashMapTest extends MapTest { 14 | @Override 15 | Class clz() { 16 | return LinkedHashMap.class; 17 | } 18 | 19 | @Override 20 | Map emptyMap() { 21 | return LinkedHashMap.empty(); 22 | } 23 | 24 | @Override 25 | protected TypeReference>> typeReferenceWithOption() { 26 | return new TypeReference>>() { 27 | }; 28 | } 29 | 30 | @Test 31 | void shouldKeepOrder() throws IOException { 32 | Map vavrObject = emptyMap().put("2", 1).put("1", 2); 33 | java.util.Map javaObject = new java.util.LinkedHashMap<>(); 34 | javaObject.put("2", 1); 35 | javaObject.put("1", 2); 36 | 37 | String json = mapper().writer().writeValueAsString(vavrObject); 38 | assertThat(json).isEqualTo(genJsonMap(javaObject)); 39 | 40 | Map restored = (Map) mapper().readValue(json, clz()); 41 | assertThat(vavrObject).isEqualTo(restored); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/map/MapJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.map; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import io.vavr.Tuple; 7 | import io.vavr.collection.HashMap; 8 | import io.vavr.collection.Map; 9 | import io.vavr.collection.TreeMap; 10 | import io.vavr.jackson.datatype.BaseTest; 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | 15 | class MapJsonMergeTest extends BaseTest { 16 | 17 | static class TestJsonMergeWithMap { 18 | @JsonMerge(OptBoolean.TRUE) 19 | public Map value = HashMap.of("foo1", "bar1"); 20 | } 21 | 22 | static class TestJsonMergeWithNestedMap { 23 | @JsonMerge(OptBoolean.TRUE) 24 | public Map> value = TreeMap.of("foo1", TreeMap.of("foo_nested", "bar_nested")); 25 | } 26 | 27 | @Test 28 | void shouldMergeString() throws Exception { 29 | TestJsonMergeWithMap result = mapper().readValue(asJson("{'value': {'foo2':'bar2'}}"), TestJsonMergeWithMap.class); 30 | 31 | assertThat(result.value) 32 | .hasSize(2) 33 | .containsExactly( 34 | Tuple.of("foo1", "bar1"), 35 | Tuple.of("foo2", "bar2")); 36 | } 37 | 38 | @Test 39 | void shouldMergeNested() throws JsonProcessingException { 40 | TestJsonMergeWithNestedMap result = mapper().readValue(asJson("{'value': {'foo1': {'foo_nested2': 'bar_nested2'}}}"), TestJsonMergeWithNestedMap.class); 41 | 42 | assertThat(result.value) 43 | .hasSize(1) 44 | .containsExactly(Tuple.of("foo1", TreeMap.of( 45 | "foo_nested", "bar_nested", 46 | "foo_nested2", "bar_nested2"))); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/map/TreeMapJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.map; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import io.vavr.Tuple; 7 | import io.vavr.collection.TreeMap; 8 | import io.vavr.jackson.datatype.BaseTest; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | class TreeMapJsonMergeTest extends BaseTest { 14 | 15 | static class TestJsonMergeWithTreeMap { 16 | @JsonMerge(OptBoolean.TRUE) 17 | public TreeMap value = TreeMap.of("foo1", "bar1"); 18 | } 19 | 20 | static class TestJsonMergeWithNestedMap { 21 | @JsonMerge(OptBoolean.TRUE) 22 | public TreeMap> value = TreeMap.of("foo1", TreeMap.of("foo_nested", "bar_nested")); 23 | } 24 | 25 | @Test 26 | void shouldMergeString() throws Exception { 27 | TestJsonMergeWithTreeMap result = mapper().readValue(asJson("{'value': {'foo2':'bar2'}}"), TestJsonMergeWithTreeMap.class); 28 | 29 | assertThat(result.value) 30 | .hasSize(2) 31 | .containsExactly( 32 | Tuple.of("foo1", "bar1"), 33 | Tuple.of("foo2", "bar2")); 34 | } 35 | 36 | @Test 37 | void shouldMergeNested() throws JsonProcessingException { 38 | TestJsonMergeWithNestedMap result = mapper().readValue(asJson("{'value': {'foo1': {'foo_nested2': 'bar_nested2'}}}"), TestJsonMergeWithNestedMap.class); 39 | 40 | assertThat(result.value) 41 | .hasSize(1) 42 | .containsExactly(Tuple.of("foo1", TreeMap.of( 43 | "foo_nested", "bar_nested", 44 | "foo_nested2", "bar_nested2"))); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/map/TreeMapTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.map; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.collection.Map; 5 | import io.vavr.collection.SortedMap; 6 | import io.vavr.collection.TreeMap; 7 | import io.vavr.control.Option; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import java.io.IOException; 11 | import java.util.Objects; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | 15 | class TreeMapTest extends MapTest { 16 | @Override 17 | Class clz() { 18 | return TreeMap.class; 19 | } 20 | 21 | @Override 22 | protected TypeReference>> typeReferenceWithOption() { 23 | return new TypeReference>>() { 24 | }; 25 | } 26 | 27 | @Override 28 | Map emptyMap() { 29 | return TreeMap.empty((o1, o2) -> o1.toString().compareTo(o2.toString())); 30 | } 31 | 32 | static class Clazz { 33 | private SortedMap set; 34 | 35 | public SortedMap getSet() { 36 | return set; 37 | } 38 | 39 | public void setSet(SortedMap set) { 40 | this.set = set; 41 | } 42 | 43 | public boolean equals(Object o) { 44 | return Objects.equals(set, ((Clazz) o).set); 45 | } 46 | 47 | public int hashCode() { 48 | return set.hashCode(); 49 | } 50 | } 51 | 52 | @Test 53 | void deserializeToSortedMap() throws IOException { 54 | Clazz c = new Clazz(); 55 | c.setSet(TreeMap.of(1, 3, 5, 7)); 56 | Clazz dc = mapper().readValue(mapper().writeValueAsString(c), Clazz.class); 57 | assertThat(dc).isEqualTo(c); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/multimap/HashMultimapTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.multimap; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.collection.HashMultimap; 5 | import io.vavr.collection.Multimap; 6 | import io.vavr.control.Option; 7 | 8 | public class HashMultimapTest extends MultimapTest { 9 | @Override 10 | Class clz() { 11 | return HashMultimap.class; 12 | } 13 | 14 | @Override 15 | Multimap emptyMap() { 16 | return HashMultimap.withSeq().empty(); 17 | } 18 | 19 | @Override 20 | protected TypeReference>> typeReferenceWithOption() { 21 | return new TypeReference>>() { 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/multimap/LinkedHashMultimapTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.multimap; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.collection.LinkedHashMultimap; 5 | import io.vavr.collection.Multimap; 6 | import io.vavr.control.Option; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.io.IOException; 10 | import java.util.Collections; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | class LinkedHashMultimapTest extends MultimapTest { 15 | @Override 16 | Class clz() { 17 | return LinkedHashMultimap.class; 18 | } 19 | 20 | @Override 21 | Multimap emptyMap() { 22 | return LinkedHashMultimap.withSeq().empty(); 23 | } 24 | 25 | @Override 26 | protected TypeReference>> typeReferenceWithOption() { 27 | return new TypeReference>>() { 28 | }; 29 | } 30 | 31 | @Test 32 | void shouldKeepOrder() throws IOException { 33 | Multimap vavrObject = emptyMap().put("2", 1).put("1", 2); 34 | java.util.Map javaObject = new java.util.LinkedHashMap<>(); 35 | javaObject.put("2", Collections.singletonList(1)); 36 | javaObject.put("1", Collections.singletonList(2)); 37 | 38 | String json = mapper().writer().writeValueAsString(vavrObject); 39 | assertThat(json).isEqualTo(genJsonMap(javaObject)); 40 | 41 | Multimap restored = (Multimap) mapper().readValue(json, clz()); 42 | assertThat(vavrObject).isEqualTo(restored); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/multimap/TreeMultimapTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.multimap; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.collection.Multimap; 5 | import io.vavr.collection.TreeMultimap; 6 | import io.vavr.control.Option; 7 | 8 | public class TreeMultimapTest extends MultimapTest { 9 | @Override 10 | Class clz() { 11 | return TreeMultimap.class; 12 | } 13 | 14 | @Override 15 | Multimap emptyMap() { 16 | return TreeMultimap.withSeq().empty((o1, o2) -> o1.toString().compareTo(o2.toString())); 17 | } 18 | 19 | @Override 20 | protected TypeReference>> typeReferenceWithOption() { 21 | return new TypeReference>>() { 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/ArrayJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.collection.Array; 6 | import io.vavr.jackson.datatype.BaseTest; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class ArrayJsonMergeTest extends BaseTest { 12 | static class TestJsonMergeWithArray { 13 | @JsonMerge(OptBoolean.TRUE) 14 | public Array value = Array.of("a", "b", "c"); 15 | } 16 | 17 | static class TestJsonMergeWithArrayConstructor { 18 | @JsonMerge(OptBoolean.TRUE) 19 | public Array value; 20 | 21 | protected TestJsonMergeWithArrayConstructor() { 22 | value = Array.of("a", "b", "c"); 23 | } 24 | 25 | public TestJsonMergeWithArrayConstructor(String d, String e) { 26 | value = Array.of(d, e); 27 | } 28 | } 29 | 30 | @Test 31 | void shouldMergeSeq() throws Exception { 32 | TestJsonMergeWithArray result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithArray.class); 33 | 34 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 35 | } 36 | 37 | @Test 38 | void shouldMergeSeqConstructor() throws Exception { 39 | TestJsonMergeWithArrayConstructor result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithArrayConstructor.class); 40 | 41 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 42 | } 43 | 44 | @Test 45 | void shouldMergeWhileRetainingValues() throws Exception { 46 | TestJsonMergeWithArrayConstructor result = mapper().readerForUpdating(new TestJsonMergeWithArrayConstructor("a", "b")) 47 | .readValue(asJson("{'value':['c', 'd', 'e', 'f']}")); 48 | 49 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/ArrayTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.core.type.TypeReference; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 7 | import io.vavr.collection.Array; 8 | import io.vavr.collection.Seq; 9 | import io.vavr.control.Option; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import java.io.IOException; 13 | import java.util.Arrays; 14 | import java.util.Date; 15 | 16 | import static org.assertj.core.api.Assertions.assertThat; 17 | 18 | class ArrayTest extends SeqTest { 19 | @Override 20 | protected Class clz() { 21 | return Array.class; 22 | } 23 | 24 | @Override 25 | protected TypeReference>> typeReferenceWithOption() { 26 | return new TypeReference>>() { 27 | }; 28 | } 29 | 30 | @Override 31 | protected Seq of(Object... objects) { 32 | return Array.ofAll(Arrays.asList(objects)); 33 | } 34 | 35 | static class FrenchDates { 36 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy", timezone = "Europe/Paris") 37 | Array dates; 38 | } 39 | 40 | @Test 41 | void serializeWithContext() throws IOException { 42 | // Given an object containing dates to serialize 43 | FrenchDates src = new FrenchDates(); 44 | src.dates = Array.of(new Date(1591308000000L)); 45 | 46 | // When serializing them using object mapper 47 | // with VAVR module and Java Time module 48 | ObjectMapper mapper = mapper().registerModule(new JavaTimeModule()); 49 | String json = mapper.writeValueAsString(src); 50 | 51 | // Then the serialization is successful 52 | assertThat(json).isEqualTo("{\"dates\":[\"05/06/2020\"]}"); 53 | 54 | // And the deserialization is successful 55 | FrenchDates restored = mapper.readValue(json, FrenchDates.class); 56 | assertThat(restored.dates).isEqualTo(src.dates); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/IndexedSeqJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.collection.Array; 6 | import io.vavr.collection.IndexedSeq; 7 | import io.vavr.jackson.datatype.BaseTest; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | class IndexedSeqJsonMergeTest extends BaseTest { 13 | static class TestJsonMergeWithSeq { 14 | @JsonMerge(OptBoolean.TRUE) 15 | public IndexedSeq value = Array.of("a", "b", "c"); 16 | } 17 | 18 | static class TestJsonMergeWithSeqConstructor { 19 | @JsonMerge(OptBoolean.TRUE) 20 | public IndexedSeq value; 21 | 22 | protected TestJsonMergeWithSeqConstructor() { 23 | value = Array.of("a", "b", "c"); 24 | } 25 | 26 | public TestJsonMergeWithSeqConstructor(String d, String e) { 27 | value = Array.of(d, e); 28 | } 29 | } 30 | 31 | @Test 32 | void shouldMergeSeq() throws Exception { 33 | TestJsonMergeWithSeq result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithSeq.class); 34 | 35 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 36 | } 37 | 38 | @Test 39 | void shouldMergeSeqConstructor() throws Exception { 40 | TestJsonMergeWithSeqConstructor result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithSeqConstructor.class); 41 | 42 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 43 | } 44 | 45 | @Test 46 | void shouldMergeWhileRetainingValues() throws Exception { 47 | TestJsonMergeWithSeqConstructor result = mapper().readerForUpdating(new TestJsonMergeWithSeqConstructor("a", "b")) 48 | .readValue(asJson("{'value':['c', 'd', 'e', 'f']}")); 49 | 50 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/IndexedSeqTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.collection.Array; 5 | import io.vavr.collection.IndexedSeq; 6 | import io.vavr.collection.Seq; 7 | import io.vavr.control.Option; 8 | 9 | import java.util.Arrays; 10 | 11 | public class IndexedSeqTest extends SeqTest { 12 | @Override 13 | protected Class clz() { 14 | return Array.class; 15 | } 16 | 17 | @Override 18 | protected TypeReference>> typeReferenceWithOption() { 19 | return new TypeReference>>() { 20 | }; 21 | } 22 | 23 | @Override 24 | protected Seq of(Object... objects) { 25 | return Array.ofAll(Arrays.asList(objects)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/ListJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.collection.List; 6 | import io.vavr.jackson.datatype.BaseTest; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class ListJsonMergeTest extends BaseTest { 12 | static class TestJsonMergeWithList { 13 | @JsonMerge(OptBoolean.TRUE) 14 | public List value = List.of("a", "b", "c"); 15 | } 16 | 17 | static class TestJsonMergeWithListConstructor { 18 | @JsonMerge(OptBoolean.TRUE) 19 | public List value; 20 | 21 | protected TestJsonMergeWithListConstructor() { 22 | value = List.of("a", "b", "c"); 23 | } 24 | 25 | public TestJsonMergeWithListConstructor(String d, String e) { 26 | value = List.of(d, e); 27 | } 28 | } 29 | 30 | @Test 31 | void shouldMergeSeq() throws Exception { 32 | TestJsonMergeWithList result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithList.class); 33 | 34 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 35 | } 36 | 37 | @Test 38 | void shouldMergeSeqConstructor() throws Exception { 39 | TestJsonMergeWithListConstructor result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithListConstructor.class); 40 | 41 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 42 | } 43 | 44 | @Test 45 | void shouldMergeWhileRetainingValues() throws Exception { 46 | TestJsonMergeWithListConstructor result = mapper().readerForUpdating(new TestJsonMergeWithListConstructor("a", "b")) 47 | .readValue(asJson("{'value':['c', 'd', 'e', 'f']}")); 48 | 49 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/ListTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 5 | import com.fasterxml.jackson.annotation.JsonTypeName; 6 | import com.fasterxml.jackson.core.type.TypeReference; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 9 | import io.vavr.collection.List; 10 | import io.vavr.collection.Seq; 11 | import io.vavr.control.Option; 12 | import org.junit.jupiter.api.Test; 13 | 14 | import java.io.IOException; 15 | import java.util.Arrays; 16 | import java.util.Date; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | class ListTest extends SeqTest { 21 | 22 | @Override 23 | protected Class clz() { 24 | return List.class; 25 | } 26 | 27 | @Override 28 | protected TypeReference>> typeReferenceWithOption() { 29 | return new TypeReference>>() { 30 | }; 31 | } 32 | 33 | @Override 34 | protected String implClzName() { 35 | return List.Cons.class.getName(); 36 | } 37 | 38 | @Override 39 | protected Seq of(Object... objects) { 40 | return List.ofAll(Arrays.asList(objects)); 41 | } 42 | 43 | @Test 44 | void defaultDeserialization() throws IOException { 45 | assertThat(List.of(1)).isEqualTo(mapper().readValue("[1]", Seq.class)); 46 | } 47 | 48 | @JsonTypeInfo( 49 | use = JsonTypeInfo.Id.NAME, 50 | include = JsonTypeInfo.As.WRAPPER_OBJECT, 51 | property = "type") 52 | @JsonTypeName("card") 53 | private static class TestSerialize { 54 | public String type = "hello"; 55 | } 56 | 57 | private static class A { 58 | public List f = List.of(new TestSerialize()); 59 | } 60 | 61 | private static class B { 62 | public java.util.List f = List.of(new TestSerialize()).toJavaList(); 63 | } 64 | 65 | @Test 66 | void jsonTypeInfo() throws IOException { 67 | String javaUtilValue = mapper().writeValueAsString(new A()); 68 | assertThat(javaUtilValue).isEqualTo(mapper().writeValueAsString(new B())); 69 | A restored = mapper().readValue(javaUtilValue, A.class); 70 | assertThat(restored.f.head().type).isEqualTo("hello"); 71 | } 72 | 73 | static class FrenchDates { 74 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy", timezone = "Europe/Paris") 75 | List dates; 76 | } 77 | 78 | @Test 79 | void serializeWithContext() throws IOException { 80 | // Given an object containing dates to serialize 81 | FrenchDates src = new FrenchDates(); 82 | src.dates = List.of(new Date(1591308000000L)); 83 | 84 | // When serializing them using object mapper 85 | // with VAVR module and Java Time module 86 | ObjectMapper mapper = mapper().registerModule(new JavaTimeModule()); 87 | String json = mapper.writeValueAsString(src); 88 | 89 | // Then the serialization is successful 90 | assertThat(json).isEqualTo("{\"dates\":[\"05/06/2020\"]}"); 91 | 92 | // And the deserialization is successful 93 | FrenchDates restored = mapper.readValue(json, FrenchDates.class); 94 | assertThat(restored.dates).isEqualTo(src.dates); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/QueueJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.collection.Queue; 6 | import io.vavr.jackson.datatype.BaseTest; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class QueueJsonMergeTest extends BaseTest { 12 | static class TestJsonMergeWithSeq { 13 | @JsonMerge(OptBoolean.TRUE) 14 | public Queue value = Queue.of("a", "b", "c"); 15 | } 16 | 17 | static class TestJsonMergeWithSeqConstructor { 18 | @JsonMerge(OptBoolean.TRUE) 19 | public Queue value; 20 | 21 | protected TestJsonMergeWithSeqConstructor() { 22 | value = Queue.of("a", "b", "c"); 23 | } 24 | 25 | public TestJsonMergeWithSeqConstructor(String d, String e) { 26 | value = Queue.of(d, e); 27 | } 28 | } 29 | 30 | @Test 31 | void shouldMergeSeq() throws Exception { 32 | TestJsonMergeWithSeq result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithSeq.class); 33 | 34 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 35 | } 36 | 37 | @Test 38 | void shouldMergeSeqConstructor() throws Exception { 39 | TestJsonMergeWithSeqConstructor result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithSeqConstructor.class); 40 | 41 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 42 | } 43 | 44 | @Test 45 | void shouldMergeWhileRetainingValues() throws Exception { 46 | TestJsonMergeWithSeqConstructor result = mapper().readerForUpdating(new TestJsonMergeWithSeqConstructor("a", "b")) 47 | .readValue(asJson("{'value':['c', 'd', 'e', 'f']}")); 48 | 49 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/QueueTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.collection.Queue; 5 | import io.vavr.collection.Seq; 6 | import io.vavr.control.Option; 7 | 8 | import java.util.Arrays; 9 | 10 | public class QueueTest extends SeqTest { 11 | @Override 12 | protected Class clz() { 13 | return Queue.class; 14 | } 15 | 16 | @Override 17 | protected TypeReference>> typeReferenceWithOption() { 18 | return new TypeReference>>() { 19 | }; 20 | } 21 | 22 | @Override 23 | protected Seq of(Object... objects) { 24 | return Queue.ofAll(Arrays.asList(objects)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/SeqJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.collection.List; 6 | import io.vavr.collection.Seq; 7 | import io.vavr.jackson.datatype.BaseTest; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | class SeqJsonMergeTest extends BaseTest { 13 | static class TestJsonMergeWithSeq { 14 | @JsonMerge(OptBoolean.TRUE) 15 | public Seq value = List.of("a", "b", "c"); 16 | } 17 | 18 | static class TestJsonMergeWithSeqConstructor { 19 | @JsonMerge(OptBoolean.TRUE) 20 | public Seq value; 21 | 22 | protected TestJsonMergeWithSeqConstructor() { 23 | value = List.of("a", "b", "c"); 24 | } 25 | 26 | public TestJsonMergeWithSeqConstructor(String d, String e) { 27 | value = List.of(d, e); 28 | } 29 | } 30 | 31 | @Test 32 | void shouldMergeSeq() throws Exception { 33 | TestJsonMergeWithSeq result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithSeq.class); 34 | 35 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 36 | } 37 | 38 | @Test 39 | void shouldMergeSeqConstructor() throws Exception { 40 | TestJsonMergeWithSeqConstructor result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithSeqConstructor.class); 41 | 42 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 43 | } 44 | 45 | @Test 46 | void shouldMergeWhileRetainingValues() throws Exception { 47 | TestJsonMergeWithSeqConstructor result = mapper().readerForUpdating(new TestJsonMergeWithSeqConstructor("a", "b")) 48 | .readValue(asJson("{'value':['c', 'd', 'e', 'f']}")); 49 | 50 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/StreamJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.collection.Stream; 6 | import io.vavr.jackson.datatype.BaseTest; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class StreamJsonMergeTest extends BaseTest { 12 | static class TestJsonMergeWithStream { 13 | @JsonMerge(OptBoolean.TRUE) 14 | public Stream value = Stream.of("a", "b", "c"); 15 | } 16 | 17 | static class TestJsonMergeWithStreamConstructor { 18 | @JsonMerge(OptBoolean.TRUE) 19 | public Stream value; 20 | 21 | protected TestJsonMergeWithStreamConstructor() { 22 | value = Stream.of("a", "b", "c"); 23 | } 24 | 25 | public TestJsonMergeWithStreamConstructor(String d, String e) { 26 | value = Stream.of(d, e); 27 | } 28 | } 29 | 30 | @Test 31 | void shouldMergeSeq() throws Exception { 32 | TestJsonMergeWithStream result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithStream.class); 33 | 34 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 35 | } 36 | 37 | @Test 38 | void shouldMergeSeqConstructor() throws Exception { 39 | TestJsonMergeWithStreamConstructor result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithStreamConstructor.class); 40 | 41 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 42 | } 43 | 44 | @Test 45 | void shouldMergeWhileRetainingValues() throws Exception { 46 | TestJsonMergeWithStreamConstructor result = mapper().readerForUpdating(new TestJsonMergeWithStreamConstructor("a", "b")) 47 | .readValue(asJson("{'value':['c', 'd', 'e', 'f']}")); 48 | 49 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/StreamTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.collection.Seq; 5 | import io.vavr.collection.Stream; 6 | import io.vavr.control.Option; 7 | 8 | import java.util.Arrays; 9 | 10 | public class StreamTest extends SeqTest { 11 | @Override 12 | protected Class clz() { 13 | return Stream.class; 14 | } 15 | 16 | @Override 17 | protected TypeReference>> typeReferenceWithOption() { 18 | return new TypeReference>>() { 19 | }; 20 | } 21 | 22 | @Override 23 | protected String implClzName() { 24 | return "io.vavr.collection.StreamModule$ConsImpl"; 25 | } 26 | 27 | @Override 28 | protected Seq of(Object... objects) { 29 | return Stream.ofAll(Arrays.asList(objects)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/VectorJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.collection.Vector; 6 | import io.vavr.jackson.datatype.BaseTest; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class VectorJsonMergeTest extends BaseTest { 12 | static class TestJsonMergeWithVector { 13 | @JsonMerge(OptBoolean.TRUE) 14 | public Vector value = Vector.of("a", "b", "c"); 15 | } 16 | 17 | static class TestJsonMergeWithVectorConstructor { 18 | @JsonMerge(OptBoolean.TRUE) 19 | public Vector value; 20 | 21 | protected TestJsonMergeWithVectorConstructor() { 22 | value = Vector.of("a", "b", "c"); 23 | } 24 | 25 | public TestJsonMergeWithVectorConstructor(String d, String e) { 26 | value = Vector.of(d, e); 27 | } 28 | } 29 | 30 | @Test 31 | void shouldMergeSeq() throws Exception { 32 | TestJsonMergeWithVector result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithVector.class); 33 | 34 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 35 | } 36 | 37 | @Test 38 | void shouldMergeSeqConstructor() throws Exception { 39 | TestJsonMergeWithVectorConstructor result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithVectorConstructor.class); 40 | 41 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 42 | } 43 | 44 | @Test 45 | void shouldMergeWhileRetainingValues() throws Exception { 46 | TestJsonMergeWithVectorConstructor result = mapper().readerForUpdating(new TestJsonMergeWithVectorConstructor("a", "b")) 47 | .readValue(asJson("{'value':['c', 'd', 'e', 'f']}")); 48 | 49 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/seq/VectorTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.seq; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.collection.Seq; 5 | import io.vavr.collection.Vector; 6 | import io.vavr.control.Option; 7 | 8 | import java.util.Arrays; 9 | 10 | public class VectorTest extends SeqTest { 11 | @Override 12 | protected Class clz() { 13 | return Vector.class; 14 | } 15 | 16 | @Override 17 | protected TypeReference>> typeReferenceWithOption() { 18 | return new TypeReference>>() { 19 | }; 20 | } 21 | 22 | @Override 23 | protected Seq of(Object... objects) { 24 | return Vector.ofAll(Arrays.asList(objects)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/set/HashSetJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.set; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.collection.HashSet; 6 | import io.vavr.jackson.datatype.BaseTest; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class HashSetJsonMergeTest extends BaseTest { 12 | static class TestJsonMergeWithHashSet { 13 | @JsonMerge(OptBoolean.TRUE) 14 | public HashSet value = HashSet.of("a", "b", "c"); 15 | } 16 | 17 | static class TestJsonMergeWithHashSetConstructor { 18 | @JsonMerge(OptBoolean.TRUE) 19 | public HashSet value; 20 | 21 | protected TestJsonMergeWithHashSetConstructor() { 22 | value = HashSet.of("a", "b", "c"); 23 | } 24 | 25 | public TestJsonMergeWithHashSetConstructor(String d, String e) { 26 | value = HashSet.of(d, e); 27 | } 28 | } 29 | 30 | @Test 31 | void shouldMergeSeq() throws Exception { 32 | TestJsonMergeWithHashSet result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithHashSet.class); 33 | 34 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 35 | } 36 | 37 | @Test 38 | void shouldMergeSeqConstructor() throws Exception { 39 | TestJsonMergeWithHashSetConstructor result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithHashSetConstructor.class); 40 | 41 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 42 | } 43 | 44 | @Test 45 | void shouldMergeWhileRetainingValues() throws Exception { 46 | TestJsonMergeWithHashSetConstructor result = mapper().readerForUpdating(new TestJsonMergeWithHashSetConstructor("a", "b")) 47 | .readValue(asJson("{'value':['c', 'd', 'e', 'f']}")); 48 | 49 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/set/HashSetTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.set; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.core.type.TypeReference; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 7 | import io.vavr.collection.HashSet; 8 | import io.vavr.collection.Set; 9 | import io.vavr.control.Option; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import java.io.IOException; 13 | import java.util.Arrays; 14 | import java.util.Date; 15 | 16 | import static org.assertj.core.api.Assertions.assertThat; 17 | 18 | class HashSetTest extends SetTest { 19 | 20 | @Override 21 | protected Class clz() { 22 | return HashSet.class; 23 | } 24 | 25 | @Override 26 | protected TypeReference> typeReference() { 27 | return new TypeReference>() { 28 | }; 29 | } 30 | 31 | @Override 32 | protected TypeReference>> typeReferenceWithOption() { 33 | return new TypeReference>>() { 34 | }; 35 | } 36 | 37 | @Override 38 | protected Set of(Object... objects) { 39 | return HashSet.ofAll(Arrays.asList(objects)); 40 | } 41 | 42 | @Test 43 | void defaultDeserialization() throws IOException { 44 | assertThat(HashSet.of(1)).isEqualTo(mapper().readValue("[1]", Set.class)); 45 | } 46 | 47 | static class FrenchDates { 48 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy", timezone = "Europe/Paris") 49 | Set dates; 50 | } 51 | 52 | @Test 53 | void serializeWithContext() throws IOException { 54 | // Given an object containing dates to serialize 55 | FrenchDates src = new FrenchDates(); 56 | src.dates = HashSet.of(new Date(1591308000000L)); 57 | 58 | // When serializing them using object mapper 59 | // with VAVR module and Java Time module 60 | ObjectMapper mapper = mapper().registerModule(new JavaTimeModule()); 61 | String json = mapper.writeValueAsString(src); 62 | 63 | // Then the serialization is successful 64 | assertThat(json).isEqualTo("{\"dates\":[\"05/06/2020\"]}"); 65 | 66 | // And the deserialization is successful 67 | FrenchDates restored = mapper.readValue(json, FrenchDates.class); 68 | assertThat(restored.dates).isEqualTo(src.dates); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/set/LinkedHashSetJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.set; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.collection.LinkedHashSet; 6 | import io.vavr.jackson.datatype.BaseTest; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class LinkedHashSetJsonMergeTest extends BaseTest { 12 | static class TestJsonMergeWithLinkedHashSet { 13 | @JsonMerge(OptBoolean.TRUE) 14 | public LinkedHashSet value = LinkedHashSet.of("a", "b", "c"); 15 | } 16 | 17 | static class TestJsonMergeWithLinkedHashSetConstructor { 18 | @JsonMerge(OptBoolean.TRUE) 19 | public LinkedHashSet value; 20 | 21 | protected TestJsonMergeWithLinkedHashSetConstructor() { 22 | value = LinkedHashSet.of("a", "b", "c"); 23 | } 24 | 25 | public TestJsonMergeWithLinkedHashSetConstructor(String d, String e) { 26 | value = LinkedHashSet.of(d, e); 27 | } 28 | } 29 | 30 | @Test 31 | void shouldMergeSeq() throws Exception { 32 | TestJsonMergeWithLinkedHashSet result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithLinkedHashSet.class); 33 | 34 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 35 | } 36 | 37 | @Test 38 | void shouldMergeSeqConstructor() throws Exception { 39 | TestJsonMergeWithLinkedHashSetConstructor result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithLinkedHashSetConstructor.class); 40 | 41 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 42 | } 43 | 44 | @Test 45 | void shouldMergeWhileRetainingValues() throws Exception { 46 | TestJsonMergeWithLinkedHashSetConstructor result = mapper().readerForUpdating(new TestJsonMergeWithLinkedHashSetConstructor("a", "b")) 47 | .readValue(asJson("{'value':['c', 'd', 'e', 'f']}")); 48 | 49 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/set/LinkedHashSetTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.set; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.collection.LinkedHashSet; 5 | import io.vavr.collection.Set; 6 | import io.vavr.control.Option; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.io.IOException; 10 | import java.util.Arrays; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | class LinkedHashSetTest extends SetTest { 15 | 16 | @Override 17 | protected Class clz() { 18 | return LinkedHashSet.class; 19 | } 20 | 21 | @Override 22 | protected TypeReference> typeReference() { 23 | return new TypeReference>() { 24 | }; 25 | } 26 | 27 | @Override 28 | protected TypeReference>> typeReferenceWithOption() { 29 | return new TypeReference>>() { 30 | }; 31 | } 32 | 33 | @Override 34 | protected Set of(Object... objects) { 35 | return LinkedHashSet.ofAll(Arrays.asList(objects)); 36 | } 37 | 38 | @Test 39 | void keepOrder() throws IOException { 40 | assertThat(LinkedHashSet.of(3, 2, 1)).isEqualTo(mapper().readValue("[3, 2, 1]", LinkedHashSet.class)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/set/SetJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.set; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.collection.HashSet; 6 | import io.vavr.collection.Set; 7 | import io.vavr.jackson.datatype.BaseTest; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | class SetJsonMergeTest extends BaseTest { 13 | static class TestJsonMergeWithSet { 14 | @JsonMerge(OptBoolean.TRUE) 15 | public Set value = HashSet.of("a", "b", "c"); 16 | } 17 | 18 | static class TestJsonMergeWithSetConstructor { 19 | @JsonMerge(OptBoolean.TRUE) 20 | public Set value; 21 | 22 | protected TestJsonMergeWithSetConstructor() { 23 | value = HashSet.of("a", "b", "c"); 24 | } 25 | 26 | public TestJsonMergeWithSetConstructor(String d, String e) { 27 | value = HashSet.of(d, e); 28 | } 29 | } 30 | 31 | @Test 32 | void shouldMergeSeq() throws Exception { 33 | TestJsonMergeWithSet result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithSet.class); 34 | 35 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 36 | } 37 | 38 | @Test 39 | void shouldMergeSeqConstructor() throws Exception { 40 | TestJsonMergeWithSetConstructor result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithSetConstructor.class); 41 | 42 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 43 | } 44 | 45 | @Test 46 | void shouldMergeWhileRetainingValues() throws Exception { 47 | TestJsonMergeWithSetConstructor result = mapper().readerForUpdating(new TestJsonMergeWithSetConstructor("a", "b")) 48 | .readValue(asJson("{'value':['c', 'd', 'e', 'f']}")); 49 | 50 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/set/TreeSetJsonMergeTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.set; 2 | 3 | import com.fasterxml.jackson.annotation.JsonMerge; 4 | import com.fasterxml.jackson.annotation.OptBoolean; 5 | import io.vavr.collection.TreeSet; 6 | import io.vavr.jackson.datatype.BaseTest; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class TreeSetJsonMergeTest extends BaseTest { 12 | static class TestJsonMergeWithTreeSet { 13 | @JsonMerge(OptBoolean.TRUE) 14 | public TreeSet value = TreeSet.of("a", "b", "c"); 15 | } 16 | 17 | static class TestJsonMergeWithTreeSetConstructor { 18 | @JsonMerge(OptBoolean.TRUE) 19 | public TreeSet value; 20 | 21 | protected TestJsonMergeWithTreeSetConstructor() { 22 | value = TreeSet.of("a", "b", "c"); 23 | } 24 | 25 | public TestJsonMergeWithTreeSetConstructor(String d, String e) { 26 | value = TreeSet.of(d, e); 27 | } 28 | } 29 | 30 | @Test 31 | void shouldMergeSeq() throws Exception { 32 | TestJsonMergeWithTreeSet result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithTreeSet.class); 33 | 34 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 35 | } 36 | 37 | @Test 38 | void shouldMergeSeqConstructor() throws Exception { 39 | TestJsonMergeWithTreeSetConstructor result = mapper().readValue(asJson("{'value':['d', 'e', 'f']}"), TestJsonMergeWithTreeSetConstructor.class); 40 | 41 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 42 | } 43 | 44 | @Test 45 | void shouldMergeWhileRetainingValues() throws Exception { 46 | TestJsonMergeWithTreeSetConstructor result = mapper().readerForUpdating(new TestJsonMergeWithTreeSetConstructor("a", "b")) 47 | .readValue(asJson("{'value':['c', 'd', 'e', 'f']}")); 48 | 49 | assertThat(result.value.toJavaList()).containsExactly("a", "b", "c", "d", "e", "f"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/set/TreeSetTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.set; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import com.fasterxml.jackson.databind.JsonMappingException; 5 | import io.vavr.collection.List; 6 | import io.vavr.collection.Set; 7 | import io.vavr.collection.SortedSet; 8 | import io.vavr.collection.TreeSet; 9 | import io.vavr.control.Option; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import java.io.IOException; 13 | import java.util.Comparator; 14 | import java.util.Objects; 15 | 16 | import static org.assertj.core.api.Assertions.assertThat; 17 | import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; 18 | 19 | class TreeSetTest extends SetTest { 20 | @Override 21 | protected Class clz() { 22 | return TreeSet.class; 23 | } 24 | 25 | @Override 26 | protected TypeReference> typeReference() { 27 | return new TypeReference>() { 28 | }; 29 | } 30 | 31 | @Override 32 | protected TypeReference>> typeReferenceWithOption() { 33 | return new TypeReference>>() { 34 | }; 35 | } 36 | 37 | @SuppressWarnings("unchecked") 38 | @Override 39 | protected Set of(Object... objects) { 40 | List> comparables = List.of(objects).map(value -> (Comparable) value); 41 | return TreeSet.ofAll(Comparator.naturalOrder(), comparables); 42 | } 43 | 44 | static class Clazz { 45 | private SortedSet set; 46 | 47 | public SortedSet getSet() { 48 | return set; 49 | } 50 | 51 | public void setSet(SortedSet set) { 52 | this.set = set; 53 | } 54 | 55 | public boolean equals(Object o) { 56 | return Objects.equals(set, ((Clazz) o).set); 57 | } 58 | 59 | public int hashCode() { 60 | return set.hashCode(); 61 | } 62 | } 63 | 64 | @Test 65 | void deserializeToSortedSet() throws IOException { 66 | Clazz c = new Clazz(); 67 | c.setSet(TreeSet.of(1, 3, 5)); 68 | Clazz dc = mapper().readValue(mapper().writeValueAsString(c), Clazz.class); 69 | assertThat(dc).isEqualTo(c); 70 | } 71 | 72 | @Test 73 | void generic1() { 74 | assertThatExceptionOfType(JsonMappingException.class).isThrownBy(() -> 75 | mapper().readValue("[1, 2]", TreeSet.class)); 76 | } 77 | 78 | @Test 79 | void generic2() { 80 | assertThatExceptionOfType(JsonMappingException.class).isThrownBy(() -> 81 | mapper().readValue("[1, 2]", new TypeReference>() { 82 | })); 83 | } 84 | 85 | @Override 86 | @Test 87 | void withOption() throws IOException { 88 | // there is nothing to test, because Option is not Comparable and we cannot deserialize a TreeSet> 89 | } 90 | 91 | static class Incomparable { 92 | private int i = 0; 93 | 94 | int getI() { 95 | return i; 96 | } 97 | 98 | void setI(int i) { 99 | this.i = i; 100 | } 101 | } 102 | 103 | @Test 104 | void generic3() { 105 | assertThatExceptionOfType(JsonMappingException.class).isThrownBy(() -> 106 | mapper().readValue("[{\"i\":1}, {\"i\":2}]", new TypeReference>() { 107 | })); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/tuples/Tuple1Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.tuples; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.Tuple; 5 | import io.vavr.Tuple1; 6 | import io.vavr.control.Option; 7 | 8 | public class Tuple1Test extends TupleTest> { 9 | 10 | @Override 11 | protected Class clz() { 12 | return Tuple1.class; 13 | } 14 | 15 | @Override 16 | protected int arity() { 17 | return 1; 18 | } 19 | 20 | @Override 21 | protected Tuple1 ofObjects(Object head, Object tail) { 22 | return Tuple.of(head); 23 | } 24 | 25 | @Override 26 | protected TypeReference>> typeReferenceWithOption() { 27 | return new TypeReference>>() { 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/tuples/Tuple2Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.tuples; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.Tuple; 5 | import io.vavr.Tuple2; 6 | import io.vavr.control.Option; 7 | 8 | public class Tuple2Test extends TupleTest> { 9 | 10 | @Override 11 | protected Class clz() { 12 | return Tuple2.class; 13 | } 14 | 15 | @Override 16 | protected int arity() { 17 | return 2; 18 | } 19 | 20 | @Override 21 | protected Tuple2 ofObjects(Object head, Object tail) { 22 | return Tuple.of(head, tail); 23 | } 24 | 25 | @Override 26 | protected TypeReference, Option>> typeReferenceWithOption() { 27 | return new TypeReference, Option>>() { 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/tuples/Tuple3Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.tuples; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.Tuple; 5 | import io.vavr.Tuple3; 6 | import io.vavr.control.Option; 7 | 8 | public class Tuple3Test extends TupleTest> { 9 | 10 | @Override 11 | protected Class clz() { 12 | return Tuple3.class; 13 | } 14 | 15 | @Override 16 | protected int arity() { 17 | return 3; 18 | } 19 | 20 | @Override 21 | protected Tuple3 ofObjects(Object head, Object tail) { 22 | return Tuple.of(head, tail, tail); 23 | } 24 | 25 | @Override 26 | protected TypeReference, Option, Option>> typeReferenceWithOption() { 27 | return new TypeReference, Option, Option>>() { 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/tuples/Tuple4Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.tuples; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.Tuple; 5 | import io.vavr.Tuple4; 6 | import io.vavr.control.Option; 7 | 8 | public class Tuple4Test extends TupleTest> { 9 | 10 | @Override 11 | protected Class clz() { 12 | return Tuple4.class; 13 | } 14 | 15 | @Override 16 | protected int arity() { 17 | return 4; 18 | } 19 | 20 | @Override 21 | protected Tuple4 ofObjects(Object head, Object tail) { 22 | return Tuple.of(head, tail, tail, tail); 23 | } 24 | 25 | @Override 26 | protected TypeReference, Option, Option, Option>> typeReferenceWithOption() { 27 | return new TypeReference, Option, Option, Option>>() { 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/tuples/Tuple5Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.tuples; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.Tuple; 5 | import io.vavr.Tuple5; 6 | import io.vavr.control.Option; 7 | 8 | public class Tuple5Test extends TupleTest> { 9 | 10 | @Override 11 | protected Class clz() { 12 | return Tuple5.class; 13 | } 14 | 15 | @Override 16 | protected int arity() { 17 | return 5; 18 | } 19 | 20 | @Override 21 | protected Tuple5 ofObjects(Object head, Object tail) { 22 | return Tuple.of(head, tail, tail, tail, tail); 23 | } 24 | 25 | @Override 26 | protected TypeReference, Option, Option, Option, Option>> typeReferenceWithOption() { 27 | return new TypeReference, Option, Option, Option, Option>>() { 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/tuples/Tuple6Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.tuples; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.Tuple; 5 | import io.vavr.Tuple6; 6 | import io.vavr.control.Option; 7 | 8 | public class Tuple6Test extends TupleTest> { 9 | 10 | @Override 11 | protected Class clz() { 12 | return Tuple6.class; 13 | } 14 | 15 | @Override 16 | protected int arity() { 17 | return 6; 18 | } 19 | 20 | @Override 21 | protected Tuple6 ofObjects(Object head, Object tail) { 22 | return Tuple.of(head, tail, tail, tail, tail, tail); 23 | } 24 | 25 | @Override 26 | protected TypeReference, Option, Option, Option, Option, Option>> typeReferenceWithOption() { 27 | return new TypeReference, Option, Option, Option, Option, Option>>() { 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/tuples/Tuple7Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.tuples; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.Tuple; 5 | import io.vavr.Tuple7; 6 | import io.vavr.control.Option; 7 | 8 | public class Tuple7Test extends TupleTest> { 9 | 10 | @Override 11 | protected Class clz() { 12 | return Tuple7.class; 13 | } 14 | 15 | @Override 16 | protected int arity() { 17 | return 7; 18 | } 19 | 20 | @Override 21 | protected Tuple7 ofObjects(Object head, Object tail) { 22 | return Tuple.of(head, tail, tail, tail, tail, tail, tail); 23 | } 24 | 25 | @Override 26 | protected TypeReference, Option, Option, Option, Option, Option, Option>> typeReferenceWithOption() { 27 | return new TypeReference, Option, Option, Option, Option, Option, Option>>() { 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/tuples/Tuple8Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.tuples; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import io.vavr.Tuple; 5 | import io.vavr.Tuple8; 6 | import io.vavr.control.Option; 7 | 8 | public class Tuple8Test extends TupleTest> { 9 | 10 | @Override 11 | protected Class clz() { 12 | return Tuple8.class; 13 | } 14 | 15 | @Override 16 | protected int arity() { 17 | return 8; 18 | } 19 | 20 | @Override 21 | protected Tuple8 ofObjects(Object head, Object tail) { 22 | return Tuple.of(head, tail, tail, tail, tail, tail, tail, tail); 23 | } 24 | 25 | @Override 26 | protected TypeReference, Option, Option, Option, Option, Option, Option, Option>> typeReferenceWithOption() { 27 | return new TypeReference, Option, Option, Option, Option, Option, Option, Option>>() { 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/tuples/TupleTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.tuples; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import io.vavr.Tuple; 6 | import io.vavr.collection.List; 7 | import io.vavr.control.Option; 8 | import io.vavr.jackson.datatype.BaseTest; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import java.io.IOException; 12 | import java.util.ArrayList; 13 | 14 | import static org.assertj.core.api.Assertions.assertThat; 15 | 16 | public abstract class TupleTest extends BaseTest { 17 | 18 | protected abstract Class clz(); 19 | 20 | protected abstract int arity(); 21 | 22 | protected abstract T ofObjects(Object head, Object tail); 23 | 24 | protected abstract TypeReference typeReferenceWithOption(); 25 | 26 | private String genJsonTuple(Object head, Object tail) { 27 | java.util.List map = new ArrayList<>(); 28 | for (int i = 0; i < arity(); i++) { 29 | map.add(i == 0 ? head : tail); 30 | } 31 | return genJsonList(map.toArray()); 32 | } 33 | 34 | @SuppressWarnings("unchecked") 35 | @Test 36 | void test1() throws IOException { 37 | T src = ofObjects(1, 17); 38 | String json = mapper().writeValueAsString(src); 39 | assertThat(json).isEqualTo(genJsonTuple(1, 17)); 40 | assertThat(mapper().readValue(json, clz())).isEqualTo(src); 41 | } 42 | 43 | @SuppressWarnings("unchecked") 44 | @Test 45 | void test2() throws IOException { 46 | ObjectMapper mapper = mapper().addMixIn(clz(), WrapperObject.class); 47 | T src = ofObjects(1, 17); 48 | String plainJson = mapper().writeValueAsString(src); 49 | String wrappedJson = mapper.writeValueAsString(src); 50 | assertThat(wrapToObject(clz().getName(), plainJson)).isEqualTo(wrappedJson); 51 | T restored = (T) mapper.readValue(wrappedJson, clz()); 52 | assertThat(restored).isEqualTo(src); 53 | } 54 | 55 | @SuppressWarnings("unchecked") 56 | @Test 57 | void test3() throws IOException { 58 | ObjectMapper mapper = mapper().addMixIn(clz(), WrapperArray.class); 59 | T src = ofObjects(1, 17); 60 | String plainJson = mapper().writeValueAsString(src); 61 | String wrappedJson = mapper.writeValueAsString(src); 62 | assertThat(wrapToArray(clz().getName(), plainJson)).isEqualTo(wrappedJson); 63 | T restored = (T) mapper.readValue(wrappedJson, clz()); 64 | assertThat(restored).isEqualTo(src); 65 | } 66 | 67 | @Test 68 | void withOption() throws IOException { 69 | verifySerialization(typeReferenceWithOption(), List.of( 70 | Tuple.of(ofObjects(Option.some("1"), Option.none()), genJsonTuple("1", null)), 71 | Tuple.of(ofObjects(Option.some("1"), Option.some("17")), genJsonTuple("1", "17")), 72 | Tuple.of(ofObjects(Option.none(), Option.some("17")), genJsonTuple(null, "17")), 73 | Tuple.of(ofObjects(Option.none(), Option.none()), genJsonTuple(null, null)) 74 | )); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/datatype/tuples/TupleXTest.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.datatype.tuples; 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 4 | import com.fasterxml.jackson.annotation.JsonTypeName; 5 | import com.fasterxml.jackson.databind.JsonMappingException; 6 | import io.vavr.Tuple; 7 | import io.vavr.Tuple0; 8 | import io.vavr.Tuple2; 9 | import io.vavr.Tuple3; 10 | import io.vavr.Tuple8; 11 | import io.vavr.jackson.datatype.BaseTest; 12 | import org.junit.jupiter.api.Test; 13 | 14 | import java.io.IOException; 15 | 16 | import static org.assertj.core.api.Assertions.assertThat; 17 | import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; 18 | 19 | class TupleXTest extends BaseTest { 20 | 21 | @Test 22 | void test0() throws IOException { 23 | Tuple0 tuple0 = Tuple0.instance(); 24 | String json = mapper().writer().writeValueAsString(tuple0); 25 | assertThat(tuple0).isEqualTo(mapper().readValue(json, Tuple0.class)); 26 | } 27 | 28 | @Test 29 | void test9() { 30 | String wrongJson = "[1, 2, 3, 4, 5, 6, 7, 8, 9]"; 31 | assertThatExceptionOfType(JsonMappingException.class).isThrownBy(() -> 32 | mapper().readValue(wrongJson, Tuple8.class)); 33 | } 34 | 35 | @Test 36 | void test10() { 37 | String json = "[1, 2, 3]"; 38 | assertThatExceptionOfType(JsonMappingException.class).isThrownBy(() -> 39 | mapper().readValue(json, Tuple2.class)); 40 | } 41 | 42 | @Test 43 | void test11() throws IOException { 44 | String json = "[1, 2]"; 45 | assertThatExceptionOfType(JsonMappingException.class).isThrownBy(() -> 46 | mapper().readValue(json, Tuple3.class)); 47 | } 48 | 49 | @JsonTypeInfo( 50 | use = JsonTypeInfo.Id.NAME, 51 | include = JsonTypeInfo.As.WRAPPER_OBJECT, 52 | property = "type") 53 | @JsonTypeName("card") 54 | private static class TestSerialize { 55 | public String type = "hello"; 56 | } 57 | 58 | private static class A { 59 | public Tuple2 f = Tuple.of(new TestSerialize(), new TestSerialize()); 60 | } 61 | 62 | @Test 63 | void jsonTypeInfo1() throws IOException { 64 | String javaUtilValue = mapper().writeValueAsString(new A()); 65 | assertThat(javaUtilValue).isEqualTo("{\"f\":[{\"card\":{\"type\":\"hello\"}},{\"card\":{\"type\":\"hello\"}}]}"); 66 | A restored = mapper().readValue(javaUtilValue, A.class); 67 | assertThat(restored.f._1.type).isEqualTo("hello"); 68 | assertThat(restored.f._2.type).isEqualTo("hello"); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/issues/Issue141Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.issues; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; 7 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 8 | import io.vavr.control.Option; 9 | import io.vavr.jackson.datatype.BaseTest; 10 | import io.vavr.jackson.datatype.VavrModule; 11 | import org.junit.jupiter.api.Test; 12 | 13 | import java.io.IOException; 14 | import java.time.YearMonth; 15 | import java.util.Optional; 16 | 17 | import static org.assertj.core.api.Assertions.assertThat; 18 | 19 | class Issue141Test extends BaseTest { 20 | 21 | static class MyJavaOptionalClass { 22 | @JsonProperty("operatingMonth") 23 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "MM-yyyy") 24 | Optional operatingMonth; 25 | } 26 | 27 | @Test 28 | void itShouldSerializeJavaOptionalYearMonthAsString() throws IOException { 29 | // Given an instance with java.util.Optional 30 | MyJavaOptionalClass obj = new MyJavaOptionalClass(); 31 | obj.operatingMonth = Optional.of(YearMonth.of(2019, 12)); 32 | 33 | // When serializing the instance using object mapper 34 | // with Java Time Module and JDK8 Module 35 | ObjectMapper objectMapper = mapper(); 36 | objectMapper.registerModule(new JavaTimeModule()); 37 | objectMapper.registerModule(new Jdk8Module()); 38 | String json = objectMapper.writeValueAsString(obj); 39 | 40 | // Then serialization is successful 41 | assertThat(json).isEqualTo("{\"operatingMonth\":\"12-2019\"}"); 42 | 43 | // And deserialization is successful 44 | MyJavaOptionalClass obj2 = objectMapper.readValue(json, MyJavaOptionalClass.class); 45 | assertThat(obj2.operatingMonth).isEqualTo(Optional.of(YearMonth.of(2019, 12))); 46 | } 47 | 48 | static class MyVavrOptionalClassWithoutFormat { 49 | @JsonProperty("operatingMonth") 50 | Option operatingMonth; 51 | } 52 | 53 | @Test 54 | void itShouldSerializeVavrOptionYearMonthAsStringWithoutJsonFormat() throws IOException { 55 | // Given an instance with io.vavr.control.Option 56 | MyVavrOptionalClassWithoutFormat obj = new MyVavrOptionalClassWithoutFormat(); 57 | obj.operatingMonth = Option.of(YearMonth.of(2019, 12)); 58 | 59 | // When serializing the instance using object mapper 60 | // with Java Time Module and VAVR Module 61 | ObjectMapper objectMapper = mapper(); 62 | objectMapper.registerModule(new JavaTimeModule()); 63 | objectMapper.registerModule(new VavrModule()); 64 | String json = objectMapper.writeValueAsString(obj); 65 | 66 | // Then serialization is successful 67 | assertThat(json).isEqualTo("{\"operatingMonth\":[2019,12]}"); 68 | MyVavrOptionalClassWithoutFormat obj2 = objectMapper.readValue(json, MyVavrOptionalClassWithoutFormat.class); 69 | 70 | // And deserialization is successful 71 | assertThat(obj2.operatingMonth).isEqualTo(Option.of(YearMonth.of(2019, 12))); 72 | } 73 | 74 | static class MyVavrOptionClassWithFormat { 75 | @JsonProperty("operatingMonth") 76 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "MM-yyyy") 77 | Option operatingMonth; 78 | } 79 | 80 | @Test 81 | void itShouldSerializeVavrOptionYearMonthAsString() throws IOException { 82 | // Given an instance with io.vavr.control.Option 83 | MyVavrOptionClassWithFormat obj = new MyVavrOptionClassWithFormat(); 84 | obj.operatingMonth = Option.of(YearMonth.of(2019, 12)); 85 | 86 | // When serializing the instance using object mapper 87 | // with Java Time Module and VAVR Module 88 | ObjectMapper objectMapper = mapper(); 89 | objectMapper.registerModule(new JavaTimeModule()); 90 | objectMapper.registerModule(new VavrModule()); 91 | String json = objectMapper.writeValueAsString(obj); 92 | 93 | // Then serialization is failed 94 | assertThat(json).isEqualTo("{\"operatingMonth\":\"12-2019\"}"); 95 | MyVavrOptionClassWithFormat obj2 = objectMapper.readValue(json, MyVavrOptionClassWithFormat.class); 96 | 97 | // And deserialization is failed 98 | assertThat(obj2.operatingMonth).isEqualTo(Option.of(YearMonth.of(2019, 12))); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/issues/Issue142Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.issues; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | import com.fasterxml.jackson.core.type.TypeReference; 5 | import com.fasterxml.jackson.databind.DeserializationContext; 6 | import com.fasterxml.jackson.databind.KeyDeserializer; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.fasterxml.jackson.databind.module.SimpleModule; 9 | import io.vavr.collection.TreeMap; 10 | import io.vavr.collection.TreeMultimap; 11 | import io.vavr.jackson.datatype.BaseTest; 12 | import io.vavr.jackson.datatype.VavrModule; 13 | import org.junit.jupiter.api.BeforeEach; 14 | import org.junit.jupiter.api.Test; 15 | 16 | import java.io.IOException; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | class Issue142Test extends BaseTest { 21 | 22 | public static class MyComparable implements Comparable { 23 | 24 | private int v; 25 | 26 | public MyComparable(int v) { 27 | this.v = v; 28 | } 29 | 30 | @Override 31 | public int compareTo(MyComparable o) { 32 | return Integer.compare(o.v, v); // reversed 33 | } 34 | 35 | @JsonValue 36 | public int getV() { 37 | return v; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "ke"; // the correct comparator should be used 43 | } 44 | } 45 | 46 | private ObjectMapper mapper; 47 | 48 | @BeforeEach 49 | void before() { 50 | mapper = new ObjectMapper(); 51 | SimpleModule module = new VavrModule() 52 | .addKeyDeserializer(MyComparable.class, new KeyDeserializer() { 53 | @Override 54 | public Object deserializeKey(String key, DeserializationContext ctxt) { 55 | return new MyComparable(Integer.parseInt(key)); 56 | } 57 | }); 58 | mapper.registerModule(module); 59 | } 60 | 61 | @Test 62 | void map() throws IOException { 63 | 64 | TreeMap mp = TreeMap.empty() 65 | .put(new MyComparable(1), 1) 66 | .put(new MyComparable(2), 2); 67 | 68 | String json = mapper.writeValueAsString(mp); 69 | assertThat(json).isEqualTo("{\"2\":2,\"1\":1}"); 70 | TreeMap restored = mapper.readValue(json, new TypeReference>() { 71 | }); 72 | assertThat(mp).isEqualTo(restored); 73 | } 74 | 75 | @Test 76 | void multimap() throws IOException { 77 | 78 | TreeMultimap mp = TreeMultimap.withSeq().empty() 79 | .put(new MyComparable(1), 1) 80 | .put(new MyComparable(2), 2); 81 | 82 | String json = mapper.writeValueAsString(mp); 83 | assertThat(json).isEqualTo("{\"2\":[2],\"1\":[1]}"); 84 | TreeMultimap restored = mapper.readValue(json, new TypeReference>() { 85 | }); 86 | assertThat(mp).isEqualTo(restored); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/issues/Issue149Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.issues; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.fasterxml.jackson.annotation.JsonUnwrapped; 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import io.vavr.collection.List; 8 | import io.vavr.control.Option; 9 | import io.vavr.control.Try; 10 | import io.vavr.jackson.datatype.BaseTest; 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 15 | 16 | /** 17 | * Vavr-Jackson should respect the @JsonUnwrapped annotation. 18 | * 19 | * Given: 20 | *
{@code
 21 |  * class Foo {
 22 |  *     @JsonUnwrapped
 23 |  *     Option getBar()
 24 |  * }
 25 |  *
 26 |  * class Bar {
 27 |  *     @JsonProperty("bar")
 28 |  *     String getValue()
 29 |  * }
 30 |  * }
31 | * 32 | * Returns 33 | *
{@code
 34 |  * {
 35 |  *    bar: {
 36 |  *        bar: ...
 37 |  *    }
 38 |  * }
 39 |  * }
40 | * 41 | * Instead of expected: 42 | *
{@code
 43 |  * {
 44 |  *    bar: ...
 45 |  * }
 46 |  * }
47 | */ 48 | public class Issue149Test extends BaseTest { 49 | 50 | @Test 51 | public void itShouldRespectTheJsonUnwrappedAnnotation() throws JsonProcessingException { 52 | // Given a mapper and a Foo object 53 | ObjectMapper mapper = mapper(); 54 | Foo foo = new Foo(); 55 | 56 | // When serializing the Foo object 57 | String json = mapper.writeValueAsString(foo); 58 | 59 | // Then the JSON should not contain the "bar" wrapper 60 | assertThat(json).isEqualTo("{\"bar\":\"bar-value\"}"); 61 | } 62 | 63 | /** 64 | * Collections cannot be unwrapped. 65 | * See {@code JsonUnwrapped} documentation. 66 | * 67 | * @throws JsonProcessingException 68 | */ 69 | @Test 70 | public void itFailsWithAnOptionList() { 71 | // Given a mapper and a FooList object 72 | ObjectMapper mapper = mapper(); 73 | FooList fooList = new FooList(); 74 | 75 | // When serializing the FooList object 76 | assertThatThrownBy(() -> mapper.writeValueAsString(fooList)) 77 | .hasRootCauseMessage("Cannot unwrap a non-bean object"); 78 | } 79 | 80 | @Test 81 | public void itFailsOnAnOptionTry() { 82 | // Given a mapper and a FooTry object 83 | ObjectMapper mapper = mapper(); 84 | FooTry fooTry = new FooTry(); 85 | 86 | // When serializing the FooTry object 87 | assertThatThrownBy(() -> mapper.writeValueAsString(fooTry)) 88 | .hasRootCauseMessage("getCause on Success"); 89 | } 90 | 91 | @Test 92 | public void itFailsOnOptionEither() { 93 | // Given a mapper and a FooEither object 94 | ObjectMapper mapper = mapper(); 95 | FooEither fooEither = new FooEither(); 96 | 97 | // When serializing the FooEither object 98 | assertThatThrownBy(() -> mapper.writeValueAsString(fooEither)) 99 | .hasRootCauseMessage("Cannot unwrap a non-bean object"); 100 | } 101 | 102 | static class Foo { 103 | @JsonUnwrapped 104 | Option bar() { 105 | return Option.of(new Bar()); 106 | } 107 | } 108 | 109 | static class Bar { 110 | @JsonProperty("bar") 111 | String getValue() { 112 | return "bar-value"; 113 | } 114 | } 115 | 116 | static class FooList { 117 | @JsonUnwrapped 118 | Option> bar() { 119 | return Option.of(List.of(new Bar())); 120 | } 121 | } 122 | 123 | static class FooTry { 124 | @JsonUnwrapped 125 | Option> bar() { 126 | return Option.of(Try.of(() -> new Bar())); 127 | } 128 | } 129 | 130 | static class FooEither { 131 | @JsonUnwrapped 132 | Option> bar() { 133 | return Option.of(io.vavr.control.Either.right(new Bar())); 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/test/java/io/vavr/jackson/issues/Issue154Test.java: -------------------------------------------------------------------------------- 1 | package io.vavr.jackson.issues; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 6 | import io.vavr.collection.List; 7 | import io.vavr.jackson.datatype.VavrModule; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import java.util.Date; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | /** 15 | * Serialize of List of Date does not follow pattern defined in {@code @JsonFormat} 16 | * https://github.com/vavr-io/vavr-jackson/issues/154 17 | */ 18 | class Issue154Test { 19 | 20 | private static class MyVavrClass { 21 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Europe/Paris") 22 | private List dates; 23 | } 24 | 25 | private static class MyJavaClass { 26 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Europe/Paris") 27 | private java.util.List dates; 28 | } 29 | 30 | @Test 31 | void itShouldSerializeVavrListWithVavrModule() throws Exception { 32 | MyVavrClass myClass = new MyVavrClass(); 33 | myClass.dates = List.of(new Date(1591221600000L), new Date(1591308000000L)); 34 | 35 | ObjectMapper mapper = new ObjectMapper(); 36 | mapper.registerModule(new VavrModule()); 37 | 38 | String json = mapper.writeValueAsString(myClass); 39 | assertThat(json).isEqualTo("{\"dates\":[\"2020-06-04\",\"2020-06-05\"]}"); 40 | } 41 | 42 | @Test 43 | void itShouldSerializeVavrListWithVavrModuleAndJavaTimeModule() throws Exception { 44 | MyVavrClass myClass = new MyVavrClass(); 45 | myClass.dates = List.of(new Date(1591221600000L), new Date(1591308000000L)); 46 | 47 | ObjectMapper mapper = new ObjectMapper(); 48 | mapper.registerModule(new VavrModule()); 49 | mapper.registerModule(new JavaTimeModule()); 50 | 51 | String json = mapper.writeValueAsString(myClass); 52 | assertThat(json).isEqualTo("{\"dates\":[\"2020-06-04\",\"2020-06-05\"]}"); 53 | } 54 | 55 | @Test 56 | void itShouldSerializeJavaListWithJavaTimeModule() throws Exception { 57 | MyJavaClass myClass = new MyJavaClass(); 58 | myClass.dates = List.of(new Date(1591221600000L), new Date(1591308000000L)).asJava(); 59 | 60 | ObjectMapper mapper = new ObjectMapper(); 61 | mapper.registerModule(new JavaTimeModule()); 62 | 63 | String json = mapper.writeValueAsString(myClass); 64 | assertThat(json).isEqualTo("{\"dates\":[\"2020-06-04\",\"2020-06-05\"]}"); 65 | } 66 | 67 | @Test 68 | void itShouldSerializeJavaListWithoutModule() throws Exception { 69 | MyJavaClass myClass = new MyJavaClass(); 70 | myClass.dates = List.of(new Date(1591221600000L), new Date(1591308000000L)).asJava(); 71 | 72 | ObjectMapper mapper = new ObjectMapper(); 73 | 74 | String json = mapper.writeValueAsString(myClass); 75 | assertThat(json).isEqualTo("{\"dates\":[\"2020-06-04\",\"2020-06-05\"]}"); 76 | } 77 | } 78 | --------------------------------------------------------------------------------