├── .github
└── dependabot.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── NOTICE
├── etc
├── license-header.txt
└── notice-template.txt
├── pom.xml
└── src
├── main
├── java-templates
│ └── org
│ │ └── n52
│ │ └── jackson
│ │ └── datatype
│ │ └── jts
│ │ └── VersionInfo.java
├── java
│ └── org
│ │ └── n52
│ │ └── jackson
│ │ └── datatype
│ │ └── jts
│ │ ├── Field.java
│ │ ├── GeometryDeserializer.java
│ │ ├── GeometrySerializer.java
│ │ ├── GeometryType.java
│ │ ├── IncludeBoundingBox.java
│ │ ├── JtsModule.java
│ │ ├── Type.java
│ │ └── TypeSafeJsonDeserializer.java
└── resources
│ └── META-INF
│ └── services
│ └── com.fasterxml.jackson.databind.Module
└── test
└── java
└── org
└── n52
└── jackson
└── datatype
└── jts
└── DeserializeTest.java
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: maven
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: "04:00"
8 | open-pull-requests-limit: 10
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### https://raw.github.com/github/gitignore/5be64312ae8e6afe2b62b550400041e90c69db6a/Global/JetBrains.gitignore
2 |
3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
5 |
6 | # User-specific stuff
7 | .idea/**/workspace.xml
8 | .idea/**/tasks.xml
9 | .idea/**/usage.statistics.xml
10 | .idea/**/dictionaries
11 | .idea/**/shelf
12 |
13 | # Generated files
14 | .idea/**/contentModel.xml
15 |
16 | # Sensitive or high-churn files
17 | .idea/**/dataSources/
18 | .idea/**/dataSources.ids
19 | .idea/**/dataSources.local.xml
20 | .idea/**/sqlDataSources.xml
21 | .idea/**/dynamic.xml
22 | .idea/**/uiDesigner.xml
23 | .idea/**/dbnavigator.xml
24 |
25 | # Gradle
26 | .idea/**/gradle.xml
27 | .idea/**/libraries
28 |
29 | # Gradle and Maven with auto-import
30 | # When using Gradle or Maven with auto-import, you should exclude module files,
31 | # since they will be recreated, and may cause churn. Uncomment if using
32 | # auto-import.
33 | .idea/modules.xml
34 | .idea/*.iml
35 | .idea/modules
36 | *.iml
37 | *.ipr
38 |
39 | # CMake
40 | cmake-build-*/
41 |
42 | # Mongo Explorer plugin
43 | .idea/**/mongoSettings.xml
44 |
45 | # File-based project format
46 | *.iws
47 |
48 | # IntelliJ
49 | out/
50 |
51 | # mpeltonen/sbt-idea plugin
52 | .idea_modules/
53 |
54 | # JIRA plugin
55 | atlassian-ide-plugin.xml
56 |
57 | # Cursive Clojure plugin
58 | .idea/replstate.xml
59 |
60 | # Crashlytics plugin (for Android Studio and IntelliJ)
61 | com_crashlytics_export_strings.xml
62 | crashlytics.properties
63 | crashlytics-build.properties
64 | fabric.properties
65 |
66 | # Editor-based Rest Client
67 | .idea/httpRequests
68 |
69 | # Android studio 3.1+ serialized cache file
70 | .idea/caches/build_file_checksums.ser
71 |
72 |
73 | ### https://raw.github.com/github/gitignore/5be64312ae8e6afe2b62b550400041e90c69db6a/Java.gitignore
74 |
75 | # Compiled class file
76 | *.class
77 |
78 | # Log file
79 | *.log
80 |
81 | # BlueJ files
82 | *.ctxt
83 |
84 | # Mobile Tools for Java (J2ME)
85 | .mtj.tmp/
86 |
87 | # Package Files #
88 | *.jar
89 | *.war
90 | *.nar
91 | *.ear
92 | *.zip
93 | *.tar.gz
94 | *.rar
95 |
96 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
97 | hs_err_pid*
98 |
99 |
100 | ### https://raw.github.com/github/gitignore/5be64312ae8e6afe2b62b550400041e90c69db6a/Global/Eclipse.gitignore
101 |
102 | .metadata
103 | bin/
104 | tmp/
105 | *.tmp
106 | *.bak
107 | *.swp
108 | *~.nib
109 | local.properties
110 | .settings/
111 | .loadpath
112 | .recommenders
113 |
114 | # External tool builders
115 | .externalToolBuilders/
116 |
117 | # Locally stored "Eclipse launch configurations"
118 | *.launch
119 |
120 | # PyDev specific (Python IDE for Eclipse)
121 | *.pydevproject
122 |
123 | # CDT-specific (C/C++ Development Tooling)
124 | .cproject
125 |
126 | # CDT- autotools
127 | .autotools
128 |
129 | # Java annotation processor (APT)
130 | .factorypath
131 |
132 | # PDT-specific (PHP Development Tools)
133 | .buildpath
134 |
135 | # sbteclipse plugin
136 | .target
137 |
138 | # Tern plugin
139 | .tern-project
140 |
141 | # TeXlipse plugin
142 | .texlipse
143 |
144 | # STS (Spring Tool Suite)
145 | .springBeans
146 |
147 | # Code Recommenders
148 | .recommenders/
149 |
150 | # Annotation Processing
151 | .apt_generated/
152 |
153 | # Scala IDE specific (Scala & Java development for Eclipse)
154 | .cache-main
155 | .scala_dependencies
156 | .worksheet
157 |
158 |
159 | ### https://raw.github.com/github/gitignore/5be64312ae8e6afe2b62b550400041e90c69db6a/Global/Windows.gitignore
160 |
161 | # Windows thumbnail cache files
162 | Thumbs.db
163 | Thumbs.db:encryptable
164 | ehthumbs.db
165 | ehthumbs_vista.db
166 |
167 | # Dump file
168 | *.stackdump
169 |
170 | # Folder config file
171 | [Dd]esktop.ini
172 |
173 | # Recycle Bin used on file shares
174 | $RECYCLE.BIN/
175 |
176 | # Windows Installer files
177 | *.cab
178 | *.msi
179 | *.msix
180 | *.msm
181 | *.msp
182 |
183 | # Windows shortcuts
184 | *.lnk
185 |
186 |
187 | ### https://raw.github.com/github/gitignore/5be64312ae8e6afe2b62b550400041e90c69db6a/Global/Linux.gitignore
188 |
189 | *~
190 |
191 | # temporary files which can be created if a process still has a handle open of a deleted file
192 | .fuse_hidden*
193 |
194 | # KDE directory preferences
195 | .directory
196 |
197 | # Linux trash folder which might appear on any partition or disk
198 | .Trash-*
199 |
200 | # .nfs files are created when an open file is removed but is still being accessed
201 | .nfs*
202 |
203 |
204 | ### https://raw.github.com/github/gitignore/5be64312ae8e6afe2b62b550400041e90c69db6a/Global/macOS.gitignore
205 |
206 | # General
207 | .DS_Store
208 | .AppleDouble
209 | .LSOverride
210 |
211 | # Icon must end with two \r
212 | Icon
213 |
214 | # Thumbnails
215 | ._*
216 |
217 | # Files that might appear in the root of a volume
218 | .DocumentRevisions-V100
219 | .fseventsd
220 | .Spotlight-V100
221 | .TemporaryItems
222 | .Trashes
223 | .VolumeIcon.icns
224 | .com.apple.timemachine.donotpresent
225 |
226 | # Directories potentially created on remote AFP share
227 | .AppleDB
228 | .AppleDesktop
229 | Network Trash Folder
230 | Temporary Items
231 | .apdisk
232 |
233 |
234 | ### https://raw.github.com/github/gitignore/5be64312ae8e6afe2b62b550400041e90c69db6a/Global/NetBeans.gitignore
235 |
236 | **/nbproject/private/
237 | **/nbproject/Makefile-*.mk
238 | **/nbproject/Package-*.bash
239 | build/
240 | nbbuild/
241 | dist/
242 | nbdist/
243 | .nb-gradle/
244 |
245 |
246 | ### https://raw.github.com/github/gitignore/5be64312ae8e6afe2b62b550400041e90c69db6a/Maven.gitignore
247 |
248 | target/
249 | pom.xml.tag
250 | pom.xml.releaseBackup
251 | pom.xml.versionsBackup
252 | pom.xml.next
253 | release.properties
254 | dependency-reduced-pom.xml
255 | buildNumber.properties
256 | .mvn/timing.properties
257 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar
258 | .mvn/wrapper/maven-wrapper.jar
259 | .idea/
260 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | dist: xenial
3 | jdk:
4 | - openjdk8
5 | - openjdk10
6 | - openjdk11
7 | matrix:
8 | include:
9 | # https://www.deps.co/guides/travis-ci-latest-java/#certificate-issues
10 | - jdk: openjdk9
11 | before_install:
12 | - rm "${JAVA_HOME}/lib/security/cacerts"
13 | - ln -s /etc/ssl/certs/java/cacerts "${JAVA_HOME}/lib/security/cacerts"
14 | - jdk: openjdk12
15 | before_install:
16 | - rm "${JAVA_HOME}/lib/security/cacerts"
17 | - ln -s /etc/ssl/certs/java/cacerts "${JAVA_HOME}/lib/security/cacerts"
18 | - jdk: openjdk13
19 | before_install:
20 | - rm "${JAVA_HOME}/lib/security/cacerts"
21 | - ln -s /etc/ssl/certs/java/cacerts "${JAVA_HOME}/lib/security/cacerts"
22 |
23 | install: true
24 | script: mvn -fae -U -B clean install -P check
25 | after_success:
26 | - curl -Ls https://git.io/deploy-maven-snapshot | bash
27 | cache:
28 | directories:
29 | - "$HOME/.m2"
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright (C) 2013 by 52 North Initiative for Geospatial Open
191 | Source Software GmbH
192 |
193 | Licensed under the Apache License, Version 2.0 (the "License");
194 | you may not use this file except in compliance with the License.
195 | You may obtain a copy of the License at
196 |
197 | http://www.apache.org/licenses/LICENSE-2.0
198 |
199 | Unless required by applicable law or agreed to in writing, software
200 | distributed under the License is distributed on an "AS IS" BASIS,
201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
202 | See the License for the specific language governing permissions and
203 | limitations under the License.
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2019 52°North Spatial Information Research GmbH
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
15 | This project includes:
16 |
17 | FindBugs-jsr305 under The Apache Software License, Version 2.0
18 | Jackson JTS datatype under The Apache Software License, Version 2.0
19 | Jackson-annotations under The Apache Software License, Version 2.0
20 | Jackson-core under The Apache Software License, Version 2.0
21 | jackson-databind under The Apache Software License, Version 2.0
22 | org.locationtech.jts:jts-core under Eclipse Public License, Version 2.0 or Eclipse Distribution License - v 1.0
23 |
24 |
--------------------------------------------------------------------------------
/etc/license-header.txt:
--------------------------------------------------------------------------------
1 | Copyright ${year} 52°North Spatial Information Research GmbH
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/etc/notice-template.txt:
--------------------------------------------------------------------------------
1 | Copyright (C) 2019 52°North Spatial Information Research GmbH
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
15 | This project includes:
16 |
17 | #GENERATED_NOTICES#
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 | org.n52
22 | parent
23 | 27
24 |
25 | 4.0.0
26 | org.n52.jackson
27 | jackson-datatype-jts
28 | 2019
29 | 2.1.0-SNAPSHOT
30 | Jackson JTS datatype
31 | Jackson JTS datatype
32 |
33 |
34 | autermann
35 | Christian Autermann
36 | c.autermann@52north.org
37 | ${project.organization.name}
38 | ${project.organization.url}
39 | GMT+1
40 |
41 |
42 |
43 | https://github.com/52North/jackson-datatype-jts
44 | scm:git:https://github.com/52North/jackson-datatype-jts.git
45 | scm:git:https://github.com/52North/jackson-datatype-jts.git
46 | HEAD
47 |
48 |
49 | GitHub issues
50 | https://github.com/52North/jackson-datatype-jts/issues?state=open
51 |
52 |
53 |
54 | The Apache Software License, Version 2.0
55 | http://www.apache.org/licenses/LICENSE-2.0.txt
56 | repo
57 | A business-friendly OSS license
58 |
59 |
60 |
61 | 2.18.3
62 |
63 |
64 |
65 | org.locationtech.jts
66 | jts-core
67 | 1.20.0
68 |
69 |
70 | com.fasterxml.jackson.core
71 | jackson-databind
72 | ${jackson-version}
73 |
74 |
75 | com.fasterxml.jackson.core
76 | jackson-annotations
77 | ${jackson-version}
78 |
79 |
80 | com.fasterxml.jackson.core
81 | jackson-core
82 | ${jackson-version}
83 |
84 |
85 | com.google.code.findbugs
86 | jsr305
87 | 3.0.2
88 |
89 |
90 |
91 |
92 | org.junit.jupiter
93 | junit-jupiter-api
94 | 5.12.1
95 | test
96 |
97 |
98 | org.assertj
99 | assertj-core
100 | 3.27.3
101 | test
102 |
103 |
104 |
105 | install
106 |
107 |
108 | org.codehaus.mojo
109 | templating-maven-plugin
110 | 1.0.0
111 |
112 |
113 | filtering-java-templates
114 |
115 | filter-sources
116 |
117 |
118 |
119 |
120 |
121 | org.apache.maven.plugins
122 | maven-release-plugin
123 |
124 | clean install
125 |
126 |
127 |
128 | org.apache.maven.plugins
129 | maven-javadoc-plugin
130 |
131 | -Xdoclint:none
132 |
133 |
134 |
135 | org.codehaus.mojo
136 | build-helper-maven-plugin
137 | 3.6.0
138 |
139 |
140 | timestamp-property
141 |
142 | timestamp-property
143 |
144 | validate
145 |
146 | current.year
147 | yyyy
148 |
149 |
150 |
151 |
152 |
153 | com.mycila
154 | license-maven-plugin
155 | false
156 |
157 | true
158 |
159 |
160 |
161 |
162 | **/*.java
163 | **/*.xml
164 |
165 |
166 |
167 | true
168 |
169 | ${project.inceptionYear}-${current.year}
170 |
171 |
172 | SLASHSTAR_STYLE
173 |
174 |
175 |
176 |
177 | format-license-headers
178 | process-resources
179 |
180 | format
181 |
182 |
183 |
184 |
185 |
186 | org.jasig.maven
187 | maven-notice-plugin
188 | 1.1.0
189 | false
190 |
191 | etc/notice-template.txt
192 |
193 | http://52north.github.io/cdn/licenses/license-mappings.xml
194 |
195 |
196 |
197 |
198 | generate-notice
199 | initialize
200 |
201 | generate
202 |
203 |
204 |
205 |
206 |
207 | com.sun.istack
208 | istack-commons-runtime
209 | 4.2.0
210 | runtime
211 |
212 |
213 | javax.xml.bind
214 | jaxb-api
215 | 2.4.0-b180830.0359
216 |
217 |
218 | javax.activation
219 | activation
220 | 1.1.1
221 |
222 |
223 | org.glassfish.jaxb
224 | jaxb-runtime
225 | 2.4.0-b180830.0438
226 |
227 |
228 |
229 |
230 |
231 |
232 |
--------------------------------------------------------------------------------
/src/main/java-templates/org/n52/jackson/datatype/jts/VersionInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2025 52°North Spatial Information Research GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.n52.jackson.datatype.jts;
17 |
18 | import com.fasterxml.jackson.core.Version;
19 |
20 | interface VersionInfo {
21 | String GROUP_ID = "${project.groupId}";
22 | String ARTIFACT_ID = "${project.artifactId}";
23 | String VERSION = "${project.version}";
24 |
25 | static Version getVersion() {
26 | String[] s = VersionInfo.VERSION.split("-");
27 | String snapshotInfo = null;
28 | int major = 0;
29 | int minor = 0;
30 | int patch = 0;
31 | if (s.length > 1) {
32 | snapshotInfo = s[1];
33 | }
34 | String[] v = s[0].split("\\.");
35 |
36 | if (v.length >= 3) {
37 | try {
38 | patch = Integer.parseInt(v[2], 10);
39 | } catch (IllegalArgumentException ignored) {
40 | }
41 | }
42 | if (v.length >= 2) {
43 | try {
44 | minor = Integer.parseInt(v[1], 10);
45 | } catch (IllegalArgumentException ignored) {
46 | }
47 | }
48 | if (v.length >= 1) {
49 | try {
50 | major = Integer.parseInt(v[0], 10);
51 | } catch (IllegalArgumentException ignored) {
52 | }
53 | }
54 |
55 | return new Version(major, minor, patch, snapshotInfo, GROUP_ID, ARTIFACT_ID);
56 | }
57 | }
--------------------------------------------------------------------------------
/src/main/java/org/n52/jackson/datatype/jts/Field.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2025 52°North Spatial Information Research GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.n52.jackson.datatype.jts;
17 |
18 | /**
19 | * JSON field names.
20 | */
21 | public interface Field {
22 | /**
23 | * The {@value} field.
24 | */
25 | String TYPE = "type";
26 | /**
27 | * The {@value} field.
28 | */
29 | String GEOMETRIES = "geometries";
30 | /**
31 | * The {@value} field.
32 | */
33 | String COORDINATES = "coordinates";
34 | /**
35 | * The {@value} field.
36 | */
37 | String BOUNDING_BOX = "bbox";
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/org/n52/jackson/datatype/jts/GeometryDeserializer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2025 52°North Spatial Information Research GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.n52.jackson.datatype.jts;
17 |
18 | import com.fasterxml.jackson.core.JsonParser;
19 | import com.fasterxml.jackson.databind.DeserializationContext;
20 | import com.fasterxml.jackson.databind.JsonDeserializer;
21 | import com.fasterxml.jackson.databind.JsonMappingException;
22 | import com.fasterxml.jackson.databind.JsonNode;
23 | import org.locationtech.jts.geom.Coordinate;
24 | import org.locationtech.jts.geom.Geometry;
25 | import org.locationtech.jts.geom.GeometryCollection;
26 | import org.locationtech.jts.geom.GeometryFactory;
27 | import org.locationtech.jts.geom.LineString;
28 | import org.locationtech.jts.geom.LinearRing;
29 | import org.locationtech.jts.geom.MultiLineString;
30 | import org.locationtech.jts.geom.MultiPoint;
31 | import org.locationtech.jts.geom.MultiPolygon;
32 | import org.locationtech.jts.geom.Point;
33 | import org.locationtech.jts.geom.Polygon;
34 | import org.locationtech.jts.geom.PrecisionModel;
35 |
36 | import javax.annotation.Nullable;
37 | import java.io.IOException;
38 | import java.util.Optional;
39 |
40 | /**
41 | * {@link JsonDeserializer} for {@link Geometry}.
42 | *
43 | * @author Christian Autermann
44 | */
45 | public class GeometryDeserializer extends JsonDeserializer {
46 | private static final int DEFAULT_SRID = 4326;
47 | private static final GeometryFactory DEFAULT_GEOMETRY_FACTORY = getDefaultGeometryFactory();
48 | private final GeometryFactory geometryFactory;
49 |
50 | /**
51 | * Creates a new {@link GeometryDeserializer}.
52 | */
53 | public GeometryDeserializer() {
54 | this(null);
55 | }
56 |
57 | /**
58 | * Creates a new {@link GeometryDeserializer}.
59 | *
60 | * @param geometryFactory The {@link GeometryFactory} to use to construct geometries.
61 | */
62 | public GeometryDeserializer(@Nullable GeometryFactory geometryFactory) {
63 | this.geometryFactory = Optional.ofNullable(geometryFactory).orElse(DEFAULT_GEOMETRY_FACTORY);
64 | }
65 |
66 | @Override
67 | public Geometry deserialize(JsonParser p, DeserializationContext context) throws IOException {
68 | return deserializeGeometry(p.readValueAs(JsonNode.class), context);
69 | }
70 |
71 | private Geometry deserializeGeometry(JsonNode node, DeserializationContext context)
72 | throws JsonMappingException {
73 | String typeName = node.get(Field.TYPE).asText();
74 |
75 | GeometryType type = GeometryType.fromString(typeName)
76 | .orElseThrow(() -> invalidGeometryType(context, typeName));
77 |
78 | switch (type) {
79 | case POINT:
80 | return deserializePoint(node, context);
81 | case MULTI_POINT:
82 | return deserializeMultiPoint(node, context);
83 | case LINE_STRING:
84 | return deserializeLineString(node, context);
85 | case MULTI_LINE_STRING:
86 | return deserializeMultiLineString(node, context);
87 | case POLYGON:
88 | return deserializePolygon(node, context);
89 | case MULTI_POLYGON:
90 | return deserializeMultiPolygon(node, context);
91 | case GEOMETRY_COLLECTION:
92 | return deserializeGeometryCollection(node, context);
93 | default:
94 | throw invalidGeometryType(context, typeName);
95 | }
96 | }
97 |
98 | private JsonMappingException invalidGeometryType(DeserializationContext context, String typeName) {
99 | return JsonMappingException.from(context, "Invalid geometry type: " + typeName);
100 | }
101 |
102 | private Point deserializePoint(JsonNode node, DeserializationContext context) throws JsonMappingException {
103 | JsonNode coordinates = getArray(node, context, Field.COORDINATES);
104 | return this.geometryFactory.createPoint(deserializeCoordinate(coordinates, context));
105 | }
106 |
107 | private Polygon deserializePolygon(JsonNode node, DeserializationContext context) throws JsonMappingException {
108 | JsonNode coordinates = getArray(node, context, Field.COORDINATES);
109 | return deserializeLinearRings(coordinates, context);
110 | }
111 |
112 | private MultiPolygon deserializeMultiPolygon(JsonNode node, DeserializationContext context)
113 | throws JsonMappingException {
114 | JsonNode coordinates = getArray(node, context, Field.COORDINATES);
115 | Polygon[] polygons = new Polygon[coordinates.size()];
116 | for (int i = 0; i != coordinates.size(); ++i) {
117 | polygons[i] = deserializeLinearRings(coordinates.get(i), context);
118 | }
119 | return this.geometryFactory.createMultiPolygon(polygons);
120 | }
121 |
122 | private MultiPoint deserializeMultiPoint(JsonNode node, DeserializationContext context)
123 | throws JsonMappingException {
124 | JsonNode coordinates = getArray(node, context, Field.COORDINATES);
125 | Coordinate[] coords = deserializeCoordinates(coordinates, context);
126 | return this.geometryFactory.createMultiPointFromCoords(coords);
127 | }
128 |
129 | private GeometryCollection deserializeGeometryCollection(JsonNode node, DeserializationContext context)
130 | throws JsonMappingException {
131 | JsonNode geometries = getArray(node, context, Field.GEOMETRIES);
132 | Geometry[] geom = new Geometry[geometries.size()];
133 | for (int i = 0; i != geometries.size(); ++i) {
134 | geom[i] = deserializeGeometry(geometries.get(i), context);
135 | }
136 | return this.geometryFactory.createGeometryCollection(geom);
137 | }
138 |
139 | private MultiLineString deserializeMultiLineString(JsonNode node, DeserializationContext context)
140 | throws JsonMappingException {
141 | JsonNode coordinates = getArray(node, context, Field.COORDINATES);
142 | LineString[] lineStrings = lineStringsFromJson(coordinates, context);
143 | return this.geometryFactory.createMultiLineString(lineStrings);
144 | }
145 |
146 | private LineString[] lineStringsFromJson(JsonNode node, DeserializationContext context)
147 | throws JsonMappingException {
148 | LineString[] strings = new LineString[node.size()];
149 | for (int i = 0; i != node.size(); ++i) {
150 | Coordinate[] coordinates = deserializeCoordinates(node.get(i), context);
151 | strings[i] = this.geometryFactory.createLineString(coordinates);
152 | }
153 | return strings;
154 | }
155 |
156 | private LineString deserializeLineString(JsonNode node, DeserializationContext context)
157 | throws JsonMappingException {
158 | JsonNode coordinates = getArray(node, context, Field.COORDINATES);
159 | Coordinate[] coords = deserializeCoordinates(coordinates, context);
160 | return this.geometryFactory.createLineString(coords);
161 | }
162 |
163 | private Coordinate[] deserializeCoordinates(JsonNode node, DeserializationContext context)
164 | throws JsonMappingException {
165 | Coordinate[] points = new Coordinate[node.size()];
166 | for (int i = 0; i != node.size(); ++i) {
167 | points[i] = deserializeCoordinate(node.get(i), context);
168 | }
169 | return points;
170 | }
171 |
172 | private Polygon deserializeLinearRings(JsonNode node, DeserializationContext context)
173 | throws JsonMappingException {
174 | LinearRing shell = deserializeLinearRing(node.get(0), context);
175 | LinearRing[] holes = new LinearRing[node.size() - 1];
176 | for (int i = 1; i < node.size(); ++i) {
177 | holes[i - 1] = deserializeLinearRing(node.get(i), context);
178 | }
179 | return this.geometryFactory.createPolygon(shell, holes);
180 | }
181 |
182 | private LinearRing deserializeLinearRing(JsonNode node, DeserializationContext context)
183 | throws JsonMappingException {
184 | Coordinate[] coordinates = deserializeCoordinates(node, context);
185 | return this.geometryFactory.createLinearRing(coordinates);
186 | }
187 |
188 | private Coordinate deserializeCoordinate(JsonNode node, DeserializationContext context)
189 | throws JsonMappingException {
190 | if (node.size() < 2) {
191 | throw JsonMappingException.from(context, String.format("Invalid number of ordinates: %d", node.size()));
192 | } else {
193 | double x = getOrdinate(node, 0, context);
194 | double y = getOrdinate(node, 1, context);
195 | if (node.size() < 3) {
196 | return new Coordinate(x, y);
197 | } else {
198 | double z = getOrdinate(node, 2, context);
199 | return new Coordinate(x, y, z);
200 | }
201 | }
202 | }
203 |
204 | private JsonNode getArray(JsonNode node, DeserializationContext context, String fieldName)
205 | throws JsonMappingException {
206 | JsonNode coordinates = node.get(fieldName);
207 | if (coordinates != null && !coordinates.isArray()) {
208 | throw JsonMappingException.from(context, "Invalid coordinates, expecting an array but got: "
209 | + coordinates.getNodeType().toString());
210 | }
211 | return coordinates;
212 | }
213 |
214 | private double getOrdinate(JsonNode node, int i, DeserializationContext context) throws JsonMappingException {
215 | JsonNode ordinate = node.get(i);
216 | if (!ordinate.isNumber()) {
217 | throw JsonMappingException.from(context, "Invalid coordinates, expecting numbers but got: "
218 | + ordinate.getNodeType().toString());
219 | }
220 | return ordinate.asDouble();
221 | }
222 |
223 | private static GeometryFactory getDefaultGeometryFactory() {
224 | return new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING), DEFAULT_SRID);
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/src/main/java/org/n52/jackson/datatype/jts/GeometrySerializer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2025 52°North Spatial Information Research GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.n52.jackson.datatype.jts;
17 |
18 | import com.fasterxml.jackson.core.JsonGenerator;
19 | import com.fasterxml.jackson.databind.JsonMappingException;
20 | import com.fasterxml.jackson.databind.JsonSerializer;
21 | import com.fasterxml.jackson.databind.SerializerProvider;
22 | import org.locationtech.jts.geom.Coordinate;
23 | import org.locationtech.jts.geom.CoordinateSequence;
24 | import org.locationtech.jts.geom.Envelope;
25 | import org.locationtech.jts.geom.Geometry;
26 | import org.locationtech.jts.geom.GeometryCollection;
27 | import org.locationtech.jts.geom.LineString;
28 | import org.locationtech.jts.geom.MultiLineString;
29 | import org.locationtech.jts.geom.MultiPoint;
30 | import org.locationtech.jts.geom.MultiPolygon;
31 | import org.locationtech.jts.geom.Point;
32 | import org.locationtech.jts.geom.Polygon;
33 |
34 | import javax.annotation.Nullable;
35 | import java.io.IOException;
36 | import java.math.RoundingMode;
37 | import java.text.DecimalFormat;
38 | import java.text.NumberFormat;
39 | import java.util.Locale;
40 | import java.util.Optional;
41 |
42 | /**
43 | * {@link JsonSerializer} for {@link Geometry}.
44 | *
45 | * @author Christian Autermann
46 | */
47 | public class GeometrySerializer extends JsonSerializer {
48 | static final int DEFAULT_DECIMAL_PLACES = 8;
49 | private final NumberFormat decimalFormat;
50 | private final IncludeBoundingBox includeBoundingBox;
51 |
52 | /**
53 | * Creates a new {@link GeometrySerializer}.
54 | */
55 | public GeometrySerializer() {
56 | this(null, DEFAULT_DECIMAL_PLACES);
57 | }
58 |
59 | /**
60 | * Creates a new {@link GeometrySerializer}.
61 | *
62 | * @param includeBoundingBox when to include a bounding box for a {@link Geometry}.
63 | */
64 | public GeometrySerializer(@Nullable IncludeBoundingBox includeBoundingBox) {
65 | this(includeBoundingBox, DEFAULT_DECIMAL_PLACES);
66 | }
67 |
68 | /**
69 | * Creates a new {@link GeometrySerializer}.
70 | *
71 | * @param includeBoundingBox when to include a bounding box for a {@link Geometry}.
72 | * @param decimalPlaces The number of decimal places for encoded coordinates.
73 | */
74 | public GeometrySerializer(@Nullable IncludeBoundingBox includeBoundingBox, int decimalPlaces) {
75 | this.includeBoundingBox = Optional.ofNullable(includeBoundingBox).orElseGet(IncludeBoundingBox::never);
76 | if (decimalPlaces < 0) {
77 | throw new IllegalArgumentException("decimalPlaces < 0");
78 | }
79 | this.decimalFormat = createNumberFormat(decimalPlaces);
80 | }
81 |
82 | private NumberFormat createNumberFormat(int decimalPlaces) {
83 | var format = DecimalFormat.getInstance(Locale.ROOT);
84 | format.setRoundingMode(RoundingMode.HALF_UP);
85 | format.setMinimumFractionDigits(0);
86 | format.setMaximumFractionDigits(decimalPlaces);
87 | format.setGroupingUsed(false);
88 | return format;
89 | }
90 |
91 | @Override
92 | public Class handledType() {
93 | return Geometry.class;
94 | }
95 |
96 | @Override
97 | public void serialize(Geometry geometry, JsonGenerator generator, SerializerProvider provider) throws IOException {
98 | if (geometry == null) {
99 | generator.writeNull();
100 | } else if (geometry instanceof Polygon) {
101 | serialize((Polygon) geometry, generator, provider);
102 | } else if (geometry instanceof Point) {
103 | serialize((Point) geometry, generator, provider);
104 | } else if (geometry instanceof MultiPoint) {
105 | serialize((MultiPoint) geometry, generator, provider);
106 | } else if (geometry instanceof MultiPolygon) {
107 | serialize((MultiPolygon) geometry, generator, provider);
108 | } else if (geometry instanceof LineString) {
109 | serialize((LineString) geometry, generator, provider);
110 | } else if (geometry instanceof MultiLineString) {
111 | serialize((MultiLineString) geometry, generator, provider);
112 | } else if (geometry instanceof GeometryCollection) {
113 | serialize((GeometryCollection) geometry, generator, provider);
114 | } else {
115 | throw JsonMappingException.from(generator,
116 | String.format("Geometry type %s is not supported.",
117 | geometry.getClass().getName()));
118 | }
119 | }
120 |
121 | private void serialize(GeometryCollection value, JsonGenerator generator, SerializerProvider provider)
122 | throws IOException {
123 | generator.writeStartObject();
124 |
125 | serializeTypeAndBoundingBox(GeometryType.GEOMETRY_COLLECTION, value, generator);
126 |
127 | generator.writeArrayFieldStart(Field.GEOMETRIES);
128 |
129 | for (int i = 0; i != value.getNumGeometries(); ++i) {
130 | serialize(value.getGeometryN(i), generator, provider);
131 | }
132 |
133 | generator.writeEndArray();
134 | generator.writeEndObject();
135 | }
136 |
137 | private void serialize(MultiPoint value, JsonGenerator generator, SerializerProvider provider)
138 | throws IOException {
139 | generator.writeStartObject();
140 | serializeTypeAndBoundingBox(GeometryType.MULTI_POINT, value, generator);
141 | generator.writeArrayFieldStart(Field.COORDINATES);
142 |
143 | for (int i = 0; i < value.getNumGeometries(); ++i) {
144 | serializeCoordinate((Point) value.getGeometryN(i), generator, provider);
145 | }
146 |
147 | generator.writeEndArray();
148 | generator.writeEndObject();
149 | }
150 |
151 | private void serialize(MultiLineString value, JsonGenerator generator, SerializerProvider provider)
152 | throws IOException {
153 | generator.writeStartObject();
154 | serializeTypeAndBoundingBox(GeometryType.MULTI_LINE_STRING, value, generator);
155 | generator.writeArrayFieldStart(Field.COORDINATES);
156 | for (int i = 0; i < value.getNumGeometries(); ++i) {
157 | serializeCoordinates((LineString) value.getGeometryN(i), generator, provider);
158 | }
159 | generator.writeEndArray();
160 | generator.writeEndObject();
161 | }
162 |
163 | private void serialize(MultiPolygon value, JsonGenerator generator, SerializerProvider provider)
164 | throws IOException {
165 | generator.writeStartObject();
166 | serializeTypeAndBoundingBox(GeometryType.MULTI_POLYGON, value, generator);
167 | generator.writeArrayFieldStart(Field.COORDINATES);
168 | for (int i = 0; i < value.getNumGeometries(); ++i) {
169 | serializeCoordinates((Polygon) value.getGeometryN(i), generator, provider);
170 | }
171 | generator.writeEndArray();
172 | generator.writeEndObject();
173 | }
174 |
175 | private void serialize(Polygon value, JsonGenerator generator, SerializerProvider provider)
176 | throws IOException {
177 | generator.writeStartObject();
178 | serializeTypeAndBoundingBox(GeometryType.POLYGON, value, generator);
179 | generator.writeFieldName(Field.COORDINATES);
180 | GeometrySerializer.this.serializeCoordinates(value, generator, provider);
181 | generator.writeEndObject();
182 | }
183 |
184 | private void serialize(LineString value, JsonGenerator generator, SerializerProvider provider)
185 | throws IOException {
186 | generator.writeStartObject();
187 | serializeTypeAndBoundingBox(GeometryType.LINE_STRING, value, generator);
188 | generator.writeFieldName(Field.COORDINATES);
189 | serializeCoordinates(value, generator, provider);
190 | generator.writeEndObject();
191 | }
192 |
193 | private void serialize(Point value, JsonGenerator generator, SerializerProvider provider)
194 | throws IOException {
195 | generator.writeStartObject();
196 | serializeTypeAndBoundingBox(GeometryType.POINT, value, generator);
197 | generator.writeFieldName(Field.COORDINATES);
198 | serializeCoordinate(value, generator, provider);
199 | generator.writeEndObject();
200 | }
201 |
202 | private void serializeTypeAndBoundingBox(GeometryType type, Geometry geometry, JsonGenerator generator)
203 | throws IOException {
204 |
205 | generator.writeStringField(Field.TYPE, type.toString());
206 |
207 | if (this.includeBoundingBox.shouldIncludeBoundingBoxFor(type) && !geometry.isEmpty()) {
208 | Envelope envelope = geometry.getEnvelopeInternal();
209 | generator.writeArrayFieldStart(Field.BOUNDING_BOX);
210 | generator.writeNumber(envelope.getMinX());
211 | generator.writeNumber(envelope.getMinY());
212 | generator.writeNumber(envelope.getMaxX());
213 | generator.writeNumber(envelope.getMaxY());
214 | generator.writeEndArray();
215 | }
216 | }
217 |
218 | private void serializeCoordinates(Polygon value, JsonGenerator generator, SerializerProvider provider)
219 | throws IOException {
220 | generator.writeStartArray();
221 | if (!value.isEmpty()) {
222 | serializeCoordinates(value.getExteriorRing(), generator, provider);
223 |
224 | for (int i = 0; i < value.getNumInteriorRing(); ++i) {
225 | serializeCoordinates(value.getInteriorRingN(i), generator, provider);
226 | }
227 | }
228 | generator.writeEndArray();
229 | }
230 |
231 | private void serializeCoordinates(LineString value, JsonGenerator generator, SerializerProvider provider)
232 | throws IOException {
233 | serializeCoordinates(value.getCoordinateSequence(), generator, provider);
234 | }
235 |
236 | private void serializeCoordinates(CoordinateSequence value, JsonGenerator generator, SerializerProvider provider)
237 | throws IOException {
238 | generator.writeStartArray();
239 | for (int i = 0; i < value.size(); ++i) {
240 | serializeCoordinate(value.getCoordinate(i), generator, provider);
241 | }
242 | generator.writeEndArray();
243 | }
244 |
245 | private void serializeCoordinate(Point value, JsonGenerator generator, SerializerProvider provider)
246 | throws IOException {
247 | serializeCoordinate(value.getCoordinate(), generator, provider);
248 | }
249 |
250 | private void serializeCoordinate(Coordinate value, JsonGenerator generator, SerializerProvider provider)
251 | throws IOException {
252 | generator.writeStartArray();
253 | generator.writeNumber(decimalFormat.format(value.getX()));
254 | generator.writeNumber(decimalFormat.format(value.getY()));
255 | if (!Double.isNaN(value.getZ()) && Double.isFinite(value.getZ())) {
256 | generator.writeNumber(decimalFormat.format(value.getZ()));
257 | }
258 | generator.writeEndArray();
259 | }
260 |
261 | }
262 |
--------------------------------------------------------------------------------
/src/main/java/org/n52/jackson/datatype/jts/GeometryType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2025 52°North Spatial Information Research GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.n52.jackson.datatype.jts;
17 |
18 | import com.fasterxml.jackson.annotation.JsonCreator;
19 | import com.fasterxml.jackson.annotation.JsonValue;
20 | import org.locationtech.jts.geom.Geometry;
21 | import org.locationtech.jts.geom.GeometryCollection;
22 | import org.locationtech.jts.geom.LineString;
23 | import org.locationtech.jts.geom.MultiLineString;
24 | import org.locationtech.jts.geom.MultiPoint;
25 | import org.locationtech.jts.geom.MultiPolygon;
26 | import org.locationtech.jts.geom.Point;
27 | import org.locationtech.jts.geom.Polygon;
28 |
29 | import java.util.Optional;
30 |
31 | public enum GeometryType {
32 | /**
33 | * Geometries of type {@link Point}.
34 | */
35 | POINT(Type.POINT),
36 | /**
37 | * Geometries of type {@link LineString}.
38 | */
39 | LINE_STRING(Type.LINE_STRING),
40 | /**
41 | * Geometries of type {@link Polygon}.
42 | */
43 | POLYGON(Type.POLYGON),
44 | /**
45 | * Geometries of type {@link MultiPoint}.
46 | */
47 | MULTI_POINT(Type.MULTI_POINT),
48 | /**
49 | * Geometries of type {@link MultiLineString}.
50 | */
51 | MULTI_LINE_STRING(Type.MULTI_LINE_STRING),
52 | /**
53 | * Geometries of type {@link MultiPolygon}.
54 | */
55 | MULTI_POLYGON(Type.MULTI_POLYGON),
56 | /**
57 | * Geometries of type {@link GeometryCollection}.
58 | */
59 | GEOMETRY_COLLECTION(Type.GEOMETRY_COLLECTION);
60 |
61 | private final String type;
62 |
63 | /**
64 | * Create a new {@link GeometryType}.
65 | *
66 | * @param type The string type.
67 | */
68 | GeometryType(String type) {
69 | this.type = type;
70 | }
71 |
72 | /**
73 | * The bit mask value of this {@link GeometryType}.
74 | *
75 | * @return The bit mask.
76 | */
77 | int mask() {
78 | return 1 << this.ordinal();
79 | }
80 |
81 | @Override
82 | @JsonValue
83 | public String toString() {
84 | return this.type;
85 | }
86 |
87 | /**
88 | * Get the geometry type from the supplied GeoJSON type value.
89 | *
90 | * @param value The GeoJSON type.
91 | * @return The {@link GeometryType}
92 | */
93 | @JsonCreator
94 | public static Optional fromString(String value) {
95 | for (GeometryType type : GeometryType.values()) {
96 | if (type.toString().equals(value)) {
97 | return Optional.of(type);
98 | }
99 | }
100 | return Optional.empty();
101 | }
102 |
103 | /**
104 | * Get the geometry type from the supplied {@link Geometry}.
105 | *
106 | * @param geometry The {@link Geometry}.
107 | * @return The {@link GeometryType}.
108 | */
109 | public static Optional forGeometry(Geometry geometry) {
110 | if (geometry == null) {
111 | return Optional.empty();
112 | } else if (geometry instanceof Polygon) {
113 | return Optional.of(POLYGON);
114 | } else if (geometry instanceof Point) {
115 | return Optional.of(POINT);
116 | } else if (geometry instanceof MultiPoint) {
117 | return Optional.of(MULTI_POINT);
118 | } else if (geometry instanceof MultiPolygon) {
119 | return Optional.of(MULTI_POLYGON);
120 | } else if (geometry instanceof LineString) {
121 | return Optional.of(LINE_STRING);
122 | } else if (geometry instanceof MultiLineString) {
123 | return Optional.of(MULTI_LINE_STRING);
124 | } else if (geometry instanceof GeometryCollection) {
125 | return Optional.of(GEOMETRY_COLLECTION);
126 | } else {
127 | return Optional.empty();
128 | }
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/org/n52/jackson/datatype/jts/IncludeBoundingBox.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2025 52°North Spatial Information Research GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.n52.jackson.datatype.jts;
17 |
18 | import org.locationtech.jts.geom.Geometry;
19 | import org.locationtech.jts.geom.GeometryCollection;
20 | import org.locationtech.jts.geom.LineString;
21 | import org.locationtech.jts.geom.MultiLineString;
22 | import org.locationtech.jts.geom.MultiPoint;
23 | import org.locationtech.jts.geom.MultiPolygon;
24 | import org.locationtech.jts.geom.Point;
25 | import org.locationtech.jts.geom.Polygon;
26 |
27 | import java.io.Serializable;
28 |
29 | /**
30 | * Class to determine when to include a bounding box for geometries.
31 | */
32 | public final class IncludeBoundingBox implements Serializable {
33 | private static final long serialVersionUID = 204690259235746434L;
34 | private final int mask;
35 |
36 | /**
37 | * Create a new {@link IncludeBoundingBox}.
38 | *
39 | * @param mask The bit mask.
40 | */
41 | private IncludeBoundingBox(int mask) {
42 | this.mask = mask;
43 | }
44 |
45 | /**
46 | * @param type The {@link GeometryType}.
47 | * @return The {@link IncludeBoundingBox}.
48 | */
49 | private IncludeBoundingBox include(GeometryType type) {
50 | return new IncludeBoundingBox(this.mask | type.mask());
51 | }
52 |
53 | /**
54 | * Include the bounding box for geometries of type {@link Point}.
55 | *
56 | * @return The {@link IncludeBoundingBox}.
57 | */
58 | public IncludeBoundingBox forPoint() {
59 | return include(GeometryType.POINT);
60 | }
61 |
62 | /**
63 | * Include the bounding box for geometries of type {@link LineString}.
64 | *
65 | * @return The {@link IncludeBoundingBox}.
66 | */
67 | public IncludeBoundingBox forLineString() {
68 | return include(GeometryType.LINE_STRING);
69 | }
70 |
71 | /**
72 | * Include the bounding box for geometries of type {@link Polygon}.
73 | *
74 | * @return The {@link IncludeBoundingBox}.
75 | */
76 | public IncludeBoundingBox forPolygon() {
77 | return include(GeometryType.POLYGON);
78 | }
79 |
80 | /**
81 | * Include the bounding box for geometries of type {@link MultiPoint}.
82 | *
83 | * @return The {@link IncludeBoundingBox}.
84 | */
85 | public IncludeBoundingBox forMultiPoint() {
86 | return include(GeometryType.MULTI_POINT);
87 | }
88 |
89 | /**
90 | * Include the bounding box for geometries of type {@link MultiLineString}.
91 | *
92 | * @return The {@link IncludeBoundingBox}.
93 | */
94 | public IncludeBoundingBox forMultiLineString() {
95 | return include(GeometryType.MULTI_LINE_STRING);
96 | }
97 |
98 | /**
99 | * Include the bounding box for geometries of type {@link MultiPolygon}.
100 | *
101 | * @return The {@link IncludeBoundingBox}.
102 | */
103 | public IncludeBoundingBox forMultiPolygon() {
104 | return include(GeometryType.MULTI_POLYGON);
105 | }
106 |
107 | /**
108 | * Include the bounding box for geometries of type {@link GeometryCollection}.
109 | *
110 | * @return The {@link IncludeBoundingBox}.
111 | */
112 | public IncludeBoundingBox forGeometryCollection() {
113 | return include(GeometryType.GEOMETRY_COLLECTION);
114 | }
115 |
116 | /**
117 | * Include the bounding box for geometries of type {@link MultiPoint}, {@link MultiLineString}, {@link MultiPolygon}
118 | * and {@link GeometryCollection}.
119 | *
120 | * @return The {@link IncludeBoundingBox}.
121 | */
122 | public IncludeBoundingBox forMultiGeometry() {
123 | return include(GeometryType.MULTI_POINT)
124 | .include(GeometryType.MULTI_LINE_STRING)
125 | .include(GeometryType.MULTI_POLYGON)
126 | .include(GeometryType.GEOMETRY_COLLECTION);
127 | }
128 |
129 | /**
130 | * Checks if the bounding box should be included for the {@link Geometry}.
131 | *
132 | * @param geometry The {@link Geometry}.
133 | * @return If the bounding box should be included.
134 | */
135 | public boolean shouldIncludeBoundingBoxFor(Geometry geometry) {
136 | return GeometryType.forGeometry(geometry).map(this::shouldIncludeBoundingBoxFor).orElse(false);
137 | }
138 |
139 | /**
140 | * Checks if the bounding box should be included for the {@link GeometryType}
141 | *
142 | * @param type The {@link GeometryType}.
143 | * @return If the bounding box should be included.
144 | */
145 | public boolean shouldIncludeBoundingBoxFor(GeometryType type) {
146 | return (this.mask & type.mask()) != 0;
147 | }
148 |
149 | /**
150 | * Never include a bounding box.
151 | *
152 | * @return The {@link IncludeBoundingBox}.
153 | */
154 | public static IncludeBoundingBox never() {
155 | return new IncludeBoundingBox(0);
156 | }
157 |
158 | /**
159 | * Always include bounding box.
160 | *
161 | * @return The {@link IncludeBoundingBox}.
162 | */
163 | public static IncludeBoundingBox always() {
164 | return never()
165 | .forGeometryCollection()
166 | .forMultiPolygon()
167 | .forMultiLineString()
168 | .forMultiPoint()
169 | .forPolygon()
170 | .forLineString()
171 | .forPoint();
172 | }
173 |
174 | /**
175 | * Always include bounding box.
176 | *
177 | * @return The {@link IncludeBoundingBox}.
178 | */
179 | public static IncludeBoundingBox exceptPoints() {
180 | return never()
181 | .forGeometryCollection()
182 | .forMultiPolygon()
183 | .forMultiLineString()
184 | .forMultiPoint()
185 | .forPolygon()
186 | .forLineString();
187 | }
188 |
189 | }
190 |
--------------------------------------------------------------------------------
/src/main/java/org/n52/jackson/datatype/jts/JtsModule.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2025 52°North Spatial Information Research GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.n52.jackson.datatype.jts;
17 |
18 | import com.fasterxml.jackson.databind.JsonDeserializer;
19 | import com.fasterxml.jackson.databind.JsonSerializer;
20 | import com.fasterxml.jackson.databind.module.SimpleModule;
21 | import org.locationtech.jts.geom.Geometry;
22 | import org.locationtech.jts.geom.GeometryCollection;
23 | import org.locationtech.jts.geom.GeometryFactory;
24 | import org.locationtech.jts.geom.LineString;
25 | import org.locationtech.jts.geom.MultiLineString;
26 | import org.locationtech.jts.geom.MultiPoint;
27 | import org.locationtech.jts.geom.MultiPolygon;
28 | import org.locationtech.jts.geom.Point;
29 | import org.locationtech.jts.geom.Polygon;
30 |
31 | import javax.annotation.Nullable;
32 |
33 | /**
34 | * {@link com.fasterxml.jackson.databind.Module} to add serialization for JTS geometries.
35 | *
36 | * @author Christian Autermann
37 | */
38 | public class JtsModule extends SimpleModule {
39 | private static final long serialVersionUID = 1L;
40 | private final GeometryFactory geometryFactory;
41 | private final IncludeBoundingBox includeBoundingBox;
42 | private final int decimalPlaces;
43 |
44 | /**
45 | * Creates a new {@link JtsModule}.
46 | */
47 | public JtsModule() {
48 | this(null, null, GeometrySerializer.DEFAULT_DECIMAL_PLACES);
49 | }
50 |
51 | /**
52 | * Creates a new {@link JtsModule}.
53 | *
54 | * @param decimalPlaces The number of decimal places for encoded coordinates.
55 | */
56 | public JtsModule(int decimalPlaces) {
57 | this(null, null, decimalPlaces);
58 | }
59 |
60 | /**
61 | * Creates a new {@link JtsModule}.
62 | *
63 | * @param geometryFactory The {@link GeometryFactory} to use to construct geometries.
64 | */
65 | public JtsModule(@Nullable GeometryFactory geometryFactory) {
66 | this(geometryFactory, null, GeometrySerializer.DEFAULT_DECIMAL_PLACES);
67 | }
68 |
69 | /**
70 | * Creates a new {@link JtsModule}.
71 | *
72 | * @param geometryFactory The {@link GeometryFactory} to use to construct geometries.
73 | * @param decimalPlaces The number of decimal places for encoded coordinates.
74 | */
75 | public JtsModule(@Nullable GeometryFactory geometryFactory, int decimalPlaces) {
76 | this(geometryFactory, null, decimalPlaces);
77 | }
78 |
79 | /**
80 | * Creates a new {@link JtsModule}.
81 | *
82 | * @param includeBoundingBox The {@link IncludeBoundingBox} to use to serialize geometries.
83 | */
84 | public JtsModule(@Nullable IncludeBoundingBox includeBoundingBox) {
85 | this(null, includeBoundingBox, GeometrySerializer.DEFAULT_DECIMAL_PLACES);
86 | }
87 |
88 | /**
89 | * Creates a new {@link JtsModule}.
90 | *
91 | * @param includeBoundingBox The {@link IncludeBoundingBox} to use to serialize geometries.
92 | * @param decimalPlaces The number of decimal places for encoded coordinates.
93 | */
94 | public JtsModule(@Nullable IncludeBoundingBox includeBoundingBox, int decimalPlaces) {
95 | this(null, includeBoundingBox, decimalPlaces);
96 | }
97 |
98 | /**
99 | * Creates a new {@link JtsModule}.
100 | *
101 | * @param geometryFactory The {@link GeometryFactory} to use to construct geometries.
102 | * @param includeBoundingBox The {@link IncludeBoundingBox} to use to serialize geometries.
103 | */
104 | public JtsModule(@Nullable GeometryFactory geometryFactory, @Nullable IncludeBoundingBox includeBoundingBox) {
105 | this(geometryFactory, includeBoundingBox, GeometrySerializer.DEFAULT_DECIMAL_PLACES);
106 | }
107 |
108 | /**
109 | * Creates a new {@link JtsModule}.
110 | *
111 | * @param geometryFactory The {@link GeometryFactory} to use to construct geometries.
112 | * @param includeBoundingBox The {@link IncludeBoundingBox} to use to serialize geometries.
113 | */
114 | public JtsModule(@Nullable GeometryFactory geometryFactory, @Nullable IncludeBoundingBox includeBoundingBox,
115 | int decimalPlaces) {
116 | super(VersionInfo.getVersion());
117 | this.geometryFactory = geometryFactory;
118 | this.includeBoundingBox = includeBoundingBox;
119 | if (decimalPlaces < 0) {
120 | throw new IllegalArgumentException("decimalPlaces < 0");
121 | }
122 | this.decimalPlaces = decimalPlaces;
123 | }
124 |
125 | @Override
126 | public void setupModule(SetupContext context) {
127 | var deserializer = getDeserializer();
128 | addSerializer(Geometry.class, getSerializer());
129 | addDeserializer(Geometry.class, deserializer);
130 | addDeserializer(Point.class, new TypeSafeJsonDeserializer<>(Point.class, deserializer));
131 | addDeserializer(LineString.class, new TypeSafeJsonDeserializer<>(LineString.class, deserializer));
132 | addDeserializer(Polygon.class, new TypeSafeJsonDeserializer<>(Polygon.class, deserializer));
133 | addDeserializer(MultiPoint.class, new TypeSafeJsonDeserializer<>(MultiPoint.class, deserializer));
134 | addDeserializer(MultiLineString.class, new TypeSafeJsonDeserializer<>(MultiLineString.class, deserializer));
135 | addDeserializer(MultiPolygon.class, new TypeSafeJsonDeserializer<>(MultiPolygon.class, deserializer));
136 | addDeserializer(GeometryCollection.class,
137 | new TypeSafeJsonDeserializer<>(GeometryCollection.class, deserializer));
138 | super.setupModule(context);
139 | }
140 |
141 | private JsonSerializer getSerializer() {
142 | return new GeometrySerializer(this.includeBoundingBox, this.decimalPlaces);
143 | }
144 |
145 | private JsonDeserializer getDeserializer() {
146 | return new GeometryDeserializer(geometryFactory);
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/src/main/java/org/n52/jackson/datatype/jts/Type.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2025 52°North Spatial Information Research GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.n52.jackson.datatype.jts;
17 |
18 | /**
19 | * GeoJSON types.
20 | */
21 | public interface Type {
22 | /**
23 | * The type {@value}.
24 | */
25 | String POINT = "Point";
26 | /**
27 | * The type {@value}.
28 | */
29 | String LINE_STRING = "LineString";
30 | /**
31 | * The type {@value}.
32 | */
33 | String POLYGON = "Polygon";
34 | /**
35 | * The type {@value}.
36 | */
37 | String MULTI_POINT = "MultiPoint";
38 | /**
39 | * The type {@value}.
40 | */
41 | String MULTI_LINE_STRING = "MultiLineString";
42 | /**
43 | * The type {@value}.
44 | */
45 | String MULTI_POLYGON = "MultiPolygon";
46 | /**
47 | * The type {@value}.
48 | */
49 | String GEOMETRY_COLLECTION = "GeometryCollection";
50 | /**
51 | * The type {@value}.
52 | */
53 | String FEATURE = "Feature";
54 | /**
55 | * The type {@value}.
56 | */
57 | String FEATURE_COLLECTION = "FeatureCollection";
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/org/n52/jackson/datatype/jts/TypeSafeJsonDeserializer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2025 52°North Spatial Information Research GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.n52.jackson.datatype.jts;
17 |
18 | import com.fasterxml.jackson.core.JsonParser;
19 | import com.fasterxml.jackson.databind.DeserializationContext;
20 | import com.fasterxml.jackson.databind.JavaType;
21 | import com.fasterxml.jackson.databind.JsonDeserializer;
22 | import com.fasterxml.jackson.databind.JsonMappingException;
23 | import com.fasterxml.jackson.databind.type.TypeFactory;
24 |
25 | import java.io.IOException;
26 | import java.util.Objects;
27 |
28 | /**
29 | * Type safe variant of a JsonDeserializer that checks the parsed value is of the right type.
30 | *
31 | * @param The type to be accepted.
32 | */
33 | public class TypeSafeJsonDeserializer extends JsonDeserializer {
34 | private final JsonDeserializer super T> delegate;
35 | private final JavaType type;
36 |
37 | /**
38 | * Creates a new {@link TypeSafeJsonDeserializer}.
39 | *
40 | * @param type The type to be accepted.
41 | * @param delegate The {@link JsonDeserializer} to delegate to.
42 | */
43 | public TypeSafeJsonDeserializer(Class extends T> type, JsonDeserializer super T> delegate) {
44 | this(TypeFactory.defaultInstance().constructType(type), delegate);
45 | }
46 |
47 | /**
48 | * Creates a new {@link TypeSafeJsonDeserializer}.
49 | *
50 | * @param type The type to be accepted.
51 | * @param delegate The {@link JsonDeserializer} to delegate to.
52 | */
53 | public TypeSafeJsonDeserializer(JavaType type, JsonDeserializer super T> delegate) {
54 | this.delegate = Objects.requireNonNull(delegate);
55 | this.type = Objects.requireNonNull(type);
56 | }
57 |
58 | @Override
59 | @SuppressWarnings("unchecked")
60 | public T deserialize(JsonParser p, DeserializationContext context) throws IOException {
61 | Object obj = delegate.deserialize(p, context);
62 | if (obj == null) {
63 | return null;
64 | } else if (type.isTypeOrSuperTypeOf(obj.getClass())) {
65 | return (T) obj;
66 | } else {
67 | throw JsonMappingException.from(context, String.format("Invalid type for %s: %s", type, obj.getClass()));
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module:
--------------------------------------------------------------------------------
1 | org.n52.jackson.datatype.jts.JtsModule
--------------------------------------------------------------------------------
/src/test/java/org/n52/jackson/datatype/jts/DeserializeTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-2025 52°North Spatial Information Research GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.n52.jackson.datatype.jts;
17 |
18 | import com.fasterxml.jackson.databind.JsonMappingException;
19 | import com.fasterxml.jackson.databind.ObjectMapper;
20 | import org.junit.jupiter.api.Test;
21 | import org.locationtech.jts.geom.MultiPolygon;
22 | import org.locationtech.jts.geom.Point;
23 |
24 | import static org.assertj.core.api.Assertions.assertThatThrownBy;
25 |
26 | public class DeserializeTest {
27 | private final ObjectMapper mapper;
28 |
29 | public DeserializeTest() {
30 | mapper = new ObjectMapper();
31 | mapper.registerModule(new JtsModule());
32 | }
33 |
34 | @Test
35 | public void throws_for_invalid_coordinates() {
36 | // GIVEN
37 | String json = "{\"multiPolygon\":{\"type\":\"MultiPolygon\","
38 | + "\"coordinates\":\"[[["
39 | + "[102.01234567890,2.01234567890],"
40 | + "[103.01234567890,2.01234567890],"
41 | + "[103.01234567890,3.01234567890],"
42 | + "[102.01234567890,3.01234567890],"
43 | + "[102.01234567890,2.01234567890]]]]\"}}}";
44 |
45 | // WHEN / THEN
46 | assertThatThrownBy(() -> mapper.readValue(json, TestObject.class))
47 | .isInstanceOf(JsonMappingException.class)
48 | .hasMessageStartingWith("Invalid coordinates, expecting an array but got: STRING");
49 | }
50 |
51 | @Test
52 | public void throws_for_invalid_coordinate_elements() {
53 | // GIVEN
54 | String json = "{\"point\":{\"type\":\"Point\",\"coordinates\":[[1,2],[3,4]]}}}";
55 |
56 | // WHEN / THEN
57 | assertThatThrownBy(() -> mapper.readValue(json, TestObject.class))
58 | .isInstanceOf(JsonMappingException.class)
59 | .hasMessageStartingWith("Invalid coordinates, expecting numbers but got: ARRAY");
60 | }
61 |
62 | public static class TestObject {
63 | private Point point;
64 | private MultiPolygon multiPolygon;
65 |
66 | public MultiPolygon getMultiPolygon() {
67 | return multiPolygon;
68 | }
69 |
70 | public void setMultiPolygon(MultiPolygon multiPolygon) {
71 | this.multiPolygon = multiPolygon;
72 | }
73 |
74 | public Point getPoint() {
75 | return point;
76 | }
77 |
78 | public void setPoint(Point point) {
79 | this.point = point;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------