Skip to content

Commit

Permalink
Migrating Commit 7fd4c1e from zalando/jackson-datatype-money
Browse files Browse the repository at this point in the history
on-behalf-of: Zalando OSS Community
Co-authored-by: whiskeysierra
Co-authored-by: jhorstmann
Co-authored-by: LappleApple
Co-authored-by: msparer
Co-authored-by: AlexanderYastrebov
Co-authored-by: aboivin
Co-authored-by: bocytko
Co-authored-by: happyherp
Co-authored-by: darioseidl
Co-authored-by: geoand
Co-authored-by: bountin
Co-authored-by: toukovk
Co-authored-by: lukasniemeier-zalando
  • Loading branch information
sri-adarsh-kumar committed Oct 22, 2024
1 parent 8dd3087 commit f29f0e3
Show file tree
Hide file tree
Showing 29 changed files with 1,854 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ 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 [JavaMoney](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 +17,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 @@ -62,6 +64,7 @@ mapper.registerModule(new JSONPModule()); // new (jakarta) json-P API
ObjectMapper mapper = JsonMapper.builder()
.addModule(new JsonOrgModule())
.addModule(new JodaMoneyModule())
.addModule(new MoneyModule())
// ONE of these (not both):
.addModule(new JSR353Module()) // old (javax) json-p API
.addModule(new JSONPModule()) // new (jakarta) json-P API
Expand Down
212 changes: 212 additions & 0 deletions javax-money/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
# Jackson Datatype Money

*Jackson Datatype Money* 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. It fills a niche, in that it
integrates JavaMoney and Jackson so that they work seamlessly together, without requiring additional
developer effort. In doing so, it aims to perform a small but repetitive task — once and for all.

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-money</artifactId>
<version>${jackson-datatype-money.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 = new ObjectMapper()
.registerModule(new MoneyModule());
```

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 = new ObjectMapper()
.registerModule(new MoneyModule().withQuotedDecimalNumbers());
```

```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 = new ObjectMapper()
.registerModule(new MoneyModule().withDefaultFormatting());
```

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

```java
ObjectMapper mapper = new ObjectMapper()
.registerModule(new MoneyModule()
.withFormatting(new CustomMonetaryAmountFormatFactory()));
```

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. If you need a different implementation, you can pass a different `MonetaryAmountFactory`
to the `MoneyModule`:

```java
ObjectMapper mapper = new ObjectMapper()
.registerModule(new MoneyModule()
.withMonetaryAmount(new CustomMonetaryAmountFactory()));
```

You can also pass in a method reference:

```java
ObjectMapper mapper = new ObjectMapper()
.registerModule(new MoneyModule()
.withMonetaryAmount(FastMoney::of));
```

*Jackson Datatype Money* comes with support for all `MonetaryAmount` implementations from Moneta, the reference
implementation of JavaMoney:

| `MonetaryAmount` Implementation | Factory |
|-------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `org.javamoney.moneta.FastMoney` | [`new MoneyModule().withFastMoney()`](src/main/java/com/fasterxml/jackson/datatype/money/FastMoneyFactory.java) |
| `org.javamoney.moneta.Money` | [`new MoneyModule().withMoney()`](src/main/java/com/fasterxml/jackson/datatype/money/MoneyFactory.java) |
| `org.javamoney.moneta.RoundedMoney` | [`new MoneyModule().withRoundedMoney()`](src/main/java/com/fasterxml/jackson/datatype/money/RoundedMoneyFactory.java) | |

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 `MoneyModule` uses the field names `amount`, `currency` and `formatted`
by default. Those names can be overridden if desired:

```java
ObjectMapper mapper = new ObjectMapper()
.registerModule(new MoneyModule()
.withAmountFieldName("value")
.withCurrencyFieldName("unit")
.withFormattedFieldName("pretty"));
```

## 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;
...
}
```
124 changes: 124 additions & 0 deletions javax-money/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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-money</artifactId>
<name>Jackson datatype: javax-money</name>
<packaging>jar</packaging>
<version>2.19.0-SNAPSHOT</version>
<description>Support for datatypes of Javax Money library (https://javamoney.github.io/)
</description>
<url>https://github.com/FasterXML/jackson-datatypes-misc</url>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<properties>
<!-- Generate PackageVersion.java into this directory. -->
<packageVersion.dir>com/fasterxml/jackson/datatype/money</packageVersion.dir>
<packageVersion.package>${project.groupId}.money</packageVersion.package>
<slf4j.version>2.0.6</slf4j.version>
<junit-jupiter.version>5.9.2</junit-jupiter.version>
</properties>

<dependencies>
<dependency>
<groupId>javax.money</groupId>
<artifactId>money-api</artifactId>
<version>1.1</version>
</dependency>

<dependency>
<groupId>org.javamoney.moneta</groupId>
<artifactId>moneta-core</artifactId>
<version>1.4.2</version>
</dependency>

<dependency>
<groupId>org.apiguardian</groupId>
<artifactId>apiguardian-api</artifactId>
<version>1.1.2</version>
</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.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</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.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jsonSchema</artifactId>
<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>

<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<version>1.1.1</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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.fasterxml.jackson.datatype.money;

import org.apiguardian.api.API;

import javax.money.MonetaryAmount;

import static org.apiguardian.api.API.Status.EXPERIMENTAL;

@API(status = EXPERIMENTAL)
public interface AmountWriter<T> {

Class<T> getType();

T write(MonetaryAmount amount);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.fasterxml.jackson.datatype.money;

import org.apiguardian.api.API;

import java.math.BigDecimal;

import static org.apiguardian.api.API.Status.EXPERIMENTAL;

@API(status = EXPERIMENTAL)
public interface BigDecimalAmountWriter extends AmountWriter<BigDecimal> {

@Override
default Class<BigDecimal> getType() {
return BigDecimal.class;
}

}
Loading

0 comments on commit f29f0e3

Please sign in to comment.