Skip to content

Commit e952bc8

Browse files
committed
docs: Add design for public GsonTypeMapper
1 parent 77d6d6f commit e952bc8

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Public GsonTypeMapper
2+
3+
## Problem
4+
5+
`Jackson2JsonTypeMapper` and `Jackson3JsonTypeMapper` are public in
6+
`com.retailsvc.http` and accept a fully-configured `ObjectMapper`, giving
7+
callers direct control over JSON serialization. The Gson equivalent,
8+
`GsonJsonMapper`, lives in `com.retailsvc.http.internal.gson`, is
9+
package-private, has only a no-arg constructor, and hard-codes a Gson
10+
instance with JSR-310 type adapters. Callers cannot pass their own `Gson`
11+
or extend the library's defaults without forking the class.
12+
13+
## Goals
14+
15+
- Expose a public, caller-configurable Gson adapter in `com.retailsvc.http`
16+
that mirrors the Jackson mappers' ergonomics.
17+
- Let callers extend the library's default (JSR-310-aware) Gson without
18+
re-implementing the type adapters.
19+
- Preserve the current auto-registration behavior: putting Gson on the
20+
classpath continues to wire up the JSR-310-aware mapper with no
21+
configuration.
22+
23+
## Non-goals
24+
25+
- Changing the auto-registration mechanism or class-name lookup in
26+
`OpenApiServer`.
27+
- Adding new JSR-310 adapters or changing the existing ISO-8601 format.
28+
- Deprecating or removing `GsonJsonMapper`; it stays as the internal
29+
implementation.
30+
31+
## Design
32+
33+
### Internal refactor: `com.retailsvc.http.internal.gson.GsonJsonMapper`
34+
35+
- Add a constructor `GsonJsonMapper(Gson gson)` that stores the supplied
36+
instance.
37+
- Existing no-arg constructor delegates to `new GsonJsonMapper(defaultGson())`
38+
where `defaultGson()` is a private static method building the current
39+
JSR-310-aware default.
40+
- Add a `Gson gson()` accessor so the public wrapper can reach the
41+
underlying instance.
42+
- `readFrom` / `readAs` / `writeTo` behavior is unchanged.
43+
44+
### New public class: `com.retailsvc.http.GsonTypeMapper`
45+
46+
`public final class GsonTypeMapper implements TypedTypeMapper`
47+
48+
Constructors:
49+
50+
- `GsonTypeMapper()` — wraps `new GsonJsonMapper()` (library default, JSR-310
51+
aware).
52+
- `GsonTypeMapper(Gson gson)` — wraps `new GsonJsonMapper(gson)`; throws
53+
`NullPointerException` via `Objects.requireNonNull` if `gson` is null.
54+
55+
Methods:
56+
57+
- `public GsonBuilder gsonBuilder()` — returns `delegate.gson().newBuilder()`,
58+
a builder pre-populated with the wrapped `Gson`'s configuration. Lets
59+
callers extend the library default in one line:
60+
`new GsonTypeMapper().gsonBuilder().registerTypeAdapter(...).create()`.
61+
- `readFrom`, `readAs`, `writeTo` — delegate to the internal mapper.
62+
63+
### `OpenApiServer`
64+
65+
No change. The auto-registration class-name constant still points at
66+
`com.retailsvc.http.internal.gson.GsonJsonMapper` and the no-arg
67+
constructor still produces a JSR-310-aware mapper.
68+
69+
### Tests
70+
71+
New `src/test/java/com/retailsvc/http/GsonTypeMapperTest.java`, JUnit 5
72+
with AssertJ, camelCase method names, static imports, curly braces on
73+
every block:
74+
75+
- `noArgConstructorRoundTripsJsr310` — verifies `Instant`,
76+
`OffsetDateTime`, `LocalDate` survive a write→read cycle as ISO-8601.
77+
- `customGsonIsUsed` — supplies a `Gson` with a custom type adapter and
78+
asserts the adapter wins over the default behavior.
79+
- `nullGsonRejected` — constructor with `null` throws `NullPointerException`.
80+
- `gsonBuilderPreservesWrappedConfig` — builds a `GsonTypeMapper` with a
81+
custom Gson, calls `gsonBuilder().create()`, and asserts the custom
82+
adapter still applies on the new instance.
83+
84+
The existing `GsonJsonMapperTest` stays as-is to cover internal behavior.
85+
86+
### Documentation
87+
88+
Update README "JSON mapping" section to add a Gson example alongside the
89+
Jackson ones, showing both `new GsonTypeMapper()` and the
90+
`gsonBuilder()` extension pattern.
91+
92+
## Risks
93+
94+
- Two public ways to obtain a Gson-backed mapper (auto-registration vs
95+
explicit `new GsonTypeMapper()`). Mitigation: README clarifies that
96+
auto-registration is for the zero-config path and `GsonTypeMapper` is
97+
for callers who want to customize.

0 commit comments

Comments
 (0)