Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move jackson-datatype-money module from zalando #48

Open
wants to merge 19 commits into
base: 2.19
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ datatype modules to support 3rd party libraries.
Currently included are:

* [jackson-datatype-joda-money](joda-money/) for [Joda-Money](https://www.joda.org/joda-money/) datatypes
* [jackson-datatype-money](javax-money/) for [JSR 354](https://github.com/JavaMoney/jsr354-api) datatypes (starting with Jackson 2.19)
* [jackson-datatype-moneta](javax-money/) for [JavaMoney Moneta](https://javamoney.github.io/) datatypes (starting with Jackson 2.19)
* JSR-353/JSON-P: 2 variants (starting with Jackson 2.12.2)
* [jackson-datatype-jsr353](jsr-353/) for older "javax.json" [JSR-353](https://www.jcp.org/en/jsr/detail?id=353) (aka JSON-P) datatypes (package `javax.json`)
* [jackson-datatype-jakarta-jsonp](jakarta-jsonp/) for newer "Jakarta" JSON-P datatypes (package `jakarta.json`)
Expand All @@ -16,6 +18,7 @@ Currently included are:
Note that this repo was created for Jackson 2.11: prior to this, individual datatype
modules had their own repositories.


## License

All modules are licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt).
Expand Down Expand Up @@ -63,6 +66,9 @@ ObjectMapper mapper = JsonMapper.builder()
.addModule(new JsonOrgModule())
.addModule(new JodaMoneyModule())
// ONE of these (not both):
.addModule(new JavaxMoneyModule())
.addModule(new MonetaMoneyModule())
// ONE of these (not both):
.addModule(new JSR353Module()) // old (javax) json-p API
.addModule(new JSONPModule()) // new (jakarta) json-P API
.build();
Expand Down
198 changes: 198 additions & 0 deletions javax-money-moneta/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# Jackson Datatype Money

*Jackson Datatype Moneta* is a [Jackson](https://github.com/codehaus/jackson) module to support JSON serialization and
deserialization of [JavaMoney](https://github.com/JavaMoney/jsr354-api) data types with special support for JavaMoney's
Moneta datatypes.

With this library, it is possible to represent monetary amounts in JSON as follows:

```json
{
"amount": 29.95,
"currency": "EUR"
}
```

## Features

- enables you to express monetary amounts in JSON
- can be used in a REST APIs
- customized field names
- localization of formatted monetary amounts
- allows you to implement RESTful API endpoints that format monetary amounts based on the Accept-Language header
- is unique and flexible

## Dependencies

- Java 8 or higher
- Any build tool using Maven Central, or direct download
- Jackson
- JavaMoney

## Installation

Add the following dependency to your project:

```xml

<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-moneta</artifactId>
<version>${jackson-datatype-moneta.version}</version>
</dependency>
```

For ultimate flexibility, this module is compatible with the official version as well as the backport of JavaMoney. The
actual version will be selected by a profile based on the current JDK version.

## Configuration

Register the module with your `ObjectMapper`:

```java
ObjectMapper mapper = JsonMapper.builder()
.addModule(new MonetaMoneyModule())
.build();
```

Alternatively, you can use the SPI capabilities:

```java
ObjectMapper mapper = new ObjectMapper()
.findAndRegisterModules();
```

### Serialization

For serialization this module currently supports
[
`javax.money.MonetaryAmount`](https://github.com/JavaMoney/jsr354-api/blob/master/src/main/java/javax/money/MonetaryAmount.java)
and will, by default, serialize it as:

```json
{
"amount": 99.95,
"currency": "EUR"
}
```

To serialize number as a JSON string, you have to configure the quoted decimal number value serializer:

```java
ObjectMapper mapper = JsonMapper.builder()
.addModule(new MonetaMoneyModule().withQuotedDecimalNumbers())
.build();
```

```json
{
"amount": "99.95",
"currency": "EUR"
}
```

### Formatting

A special feature for serializing monetary amounts is *formatting*, which is **disabled by default**. To enable it, you
have to either enable default formatting:

```java
ObjectMapper mapper = JsonMapper.builder()
.addModule(new MonetaMoneyModule().withDefaultFormatting())
.build();
```

... or pass in a `MonetaryAmountFormatFactory` implementation to the `MonetaMoneyModule`:

```java
ObjectMapper mapper = JsonMapper.builder()
.addModule(new MonetaMoneyModule()
.withFormatting(new CustomMonetaryAmountFormatFactory()))
.build();
```

The default formatting delegates directly to `MonetaryFormats.getAmountFormat(Locale, String...)`.

Formatting only affects the serialization and can be customized based on the *current* locale, as defined by the
[
`SerializationConfig`](https://fasterxml.github.io/jackson-databind/javadoc/2.0.0/com/fasterxml/jackson/databind/SerializationConfig.html#with\(java.util.Locale\)).
This allows to implement RESTful API endpoints
that format monetary amounts based on the `Accept-Language` header.

The first example serializes a monetary amount using the `de_DE` locale:

```java
ObjectWriter writer = mapper.writer().with(Locale.GERMANY);
writer.writeValueAsString(Money.of(29.95, "EUR"));
```

```json
{
"amount": 29.95,
"currency": "EUR",
"formatted": "29,95 EUR"
}
```

The following example uses `en_US`:

```java
ObjectWriter writer = mapper.writer().with(Locale.US);
writer.writeValueAsString(Money.of(29.95, "USD"));
```

```json
{
"amount": 29.95,
"currency": "USD",
"formatted": "USD29.95"
}
```

More sophisticated formatting rules can be supported by implementing `MonetaryAmountFormatFactory` directly.

### Deserialization

This module will use `org.javamoney.moneta.Money` as an implementation for `javax.money.MonetaryAmount` by default when
deserializing money values.

In addition, this module comes with support for all `MonetaryAmount` implementations from Moneta, the reference
implementation of JavaMoney:

| `MonetaryAmount` Implementation | Factory |
|-------------------------------------|----------------------------------------------|
| `org.javamoney.moneta.FastMoney` | `new MonetaMoneyModule().withFastMoney()` |
| `org.javamoney.moneta.Money` | `new MonetaMoneyModule().withMoney()` |
| `org.javamoney.moneta.RoundedMoney` | `new MonetaMoneyModule().withRoundedMoney()` | |

Module supports deserialization of amount number from JSON number as well as from JSON string without any special
configuration required.

### Custom Field Names

As you have seen in the previous examples the `MonetaMoneyModule` uses the field names `amount`, `currency` and
`formatted`
by default. Those names can be overridden if desired:

```java
ObjectMapper mapper = JsonMapper.builder()
.addModule(new MonetaMoneyModule()
.withAmountFieldName("value")
.withCurrencyFieldName("unit")
.withFormattedFieldName("pretty"))
.build();
```

## Usage

After registering and configuring the module you're now free to directly use `MonetaryAmount` in your data types:

```java
import javax.money.MonetaryAmount;

public class Product {
private String sku;
private MonetaryAmount price;
...
}
```
112 changes: 112 additions & 0 deletions javax-money-moneta/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- This module was also published with a richer model, Gradle metadata, -->
<!-- which should be used instead. Do not delete the following line which -->
<!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
<!-- that they should prefer consuming it instead. -->
<!-- do_not_remove: published-with-gradle-metadata -->
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatypes-misc-parent</artifactId>
<version>2.19.0-SNAPSHOT</version>
</parent>
<artifactId>jackson-datatype-moneta</artifactId>
<name>Jackson datatype: javax-money-moneta</name>
<packaging>jar</packaging>
<version>2.19.0-SNAPSHOT</version>
<description>Support for datatypes of Money API spec from JSR 354 (https://javamoney.github.io/api.html)
</description>
<url>https://github.com/FasterXML/jackson-datatypes-misc</url>
<licenses>
<license>
<name>MIT License</name>
<url>https://opensource.org/licenses/MIT</url>
<distribution>repo</distribution>
</license>
</licenses>
<properties>
<!-- Generate PackageVersion.java into this directory. -->
<packageVersion.dir>com/fasterxml/jackson/datatype/money/moneta</packageVersion.dir>
<packageVersion.package>${project.groupId}.money.moneta</packageVersion.package>
<slf4j.version>2.0.6</slf4j.version>
</properties>

<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-money</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.money</groupId>
<artifactId>money-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.javamoney</groupId>
<artifactId>moneta</artifactId>
<version>1.4.4</version>
<type>pom</type>
</dependency>

<dependency>
<groupId>org.apiguardian</groupId>
<artifactId>apiguardian-api</artifactId>
<version>1.1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<scope>provided</scope>
</dependency>

<!-- test -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.kjetland</groupId>
<artifactId>mbknor-jackson-jsonschema_2.12</artifactId>
<version>1.0.39</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
</plugin>
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Loading