-
Notifications
You must be signed in to change notification settings - Fork 23
/
json.html
767 lines (624 loc) · 65.6 KB
/
json.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"-->
<link rel="stylesheet" href="/gfx/bootstrap.min.css">
<link rel="stylesheet" href="/gfx/main.css">
<link rel="stylesheet" href="/gfx/code.css">
<title>JSON serialization</title>
</head>
<body class="page">
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-PMJSKV"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-PMJSKV');</script>
<!-- End Google Tag Manager -->
<header>
<div class="container">
<a href="/">Immutables</a> ←
<h1>JSON serialization <iframe src="https://ghbtns.com/github-btn.html?user=immutables&repo=immutables&type=star&count=true&size=large" frameborder="0" scrolling="0" width="160px" height="30px"></iframe>
</h1>
</div>
</header>
<aside id="toc"></aside>
<section class="documentation">
<h2 id="overview">Overview</h2>
<p>It’s not uncommon to use immutable object as messages or documents to transfer or store data.
JSON is a simple and flexible format. Moreover, using libraries like <a href="http://wiki.fasterxml.com/JacksonHome">Jackson</a>, you can use various additional textual and binary formats:
<a href="https://github.com/FasterXML/jackson-dataformat-smile">Smile</a>,
<a href="https://github.com/michel-kraemer/bson4jackson">BSON</a>,
<a href="https://github.com/FasterXML/jackson-dataformat-cbor">CBOR</a>,
<a href="https://github.com/FasterXML/jackson-dataformat-yaml">YAML</a>… etc.</p>
<p><em>Immutables</em> JSON integration underwent an overhaul for 2.0. This made integration a lot less exotic and more comprehensible.</p>
<p>Instead of the old generated marshaler infrastructure based on <em>Jackson</em> streaming (jackson-core), two new integrations available:</p>
<ul>
<li>Simplified <em>Jackson</em> integration
<ul>
<li>Generation of <code class="language-plaintext highlighter-rouge">@JsonCreator</code>, <code class="language-plaintext highlighter-rouge">@JsonProperty</code> annotations and a helper class.</li>
<li>Delegates everything back to Jackson using its powerful binding engine</li>
</ul>
</li>
<li>Comprehensive <em>Gson</em> integration
<ul>
<li>No custom runtime APIs, Gson APIs are used</li>
<li>Generation of <em>TypeAdapterFactories</em> which use no reflection.</li>
<li>Helper classes to integrate <em>Gson</em> streaming with <em>Jackson</em> streaming to squeeze maximum performance.</li>
</ul>
</li>
</ul>
<p><a name="jackson"></a>
Jackson
——-</p>
<p>Overall <em>Jackson</em> doesn’t require any serious code generation to be flexible and highly performant
on the JVM. No additional dependencies are required except for <em>Immutables</em> processor and <em>Jackson</em>
library. It is recommended to use <em>Jackson</em> version 2.4+, but earlier versions can work also.</p>
<p>Integration works by generating <code class="language-plaintext highlighter-rouge">@JsonCreator</code> factory method and puts <code class="language-plaintext highlighter-rouge">@JsonProperty</code>
annotations on immutable implementations. To enable this, you should use <code class="language-plaintext highlighter-rouge">@JsonSerialize</code>
or <code class="language-plaintext highlighter-rouge">@JsonDeserialize</code> annotation. Point to an immutable
implementation class in <code class="language-plaintext highlighter-rouge">as</code> annotation attribute:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">com.fasterxml.jackson.annotation.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.immutables.value.Value</span><span class="o">;</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="nd">@JsonSerialize</span><span class="o">(</span><span class="n">as</span> <span class="o">=</span> <span class="nc">ImmutableVal</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="nd">@JsonDeserialize</span><span class="o">(</span><span class="n">as</span> <span class="o">=</span> <span class="nc">ImmutableVal</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="kd">interface</span> <span class="nc">Val</span> <span class="o">{</span>
<span class="kt">int</span> <span class="nf">a</span><span class="o">();</span>
<span class="nd">@JsonProperty</span><span class="o">(</span><span class="s">"b"</span><span class="o">)</span> <span class="nc">String</span> <span class="nf">second</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>
<p>While <code class="language-plaintext highlighter-rouge">ImmutableVal</code> may not be generated yet, the above will compile properly.
<code class="language-plaintext highlighter-rouge">as = ImmutableVal.class</code> attribute have to be added if your codebase predominantly use abstract value
as a canonical type, if you mostly use immutable type, then it’s not required to use <code class="language-plaintext highlighter-rouge">as</code> attribute.
You can use <code class="language-plaintext highlighter-rouge">@JsonProperty</code> to customize JSON field names. You can freely use any other facilities
of the <em>Jackson</em> library if applicable.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">ObjectMapper</span> <span class="n">objectMapper</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ObjectMapper</span><span class="o">();</span>
<span class="nc">String</span> <span class="n">json</span> <span class="o">=</span> <span class="n">objectMapper</span><span class="o">.</span><span class="na">writeValueAsString</span><span class="o">(</span>
<span class="nc">ImmutableVal</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">a</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
<span class="o">.</span><span class="na">second</span><span class="o">(</span><span class="s">"B"</span><span class="o">)</span>
<span class="o">.</span><span class="na">build</span><span class="o">());</span>
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span> <span class="dl">"</span><span class="s2">a</span><span class="dl">"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">b</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span> <span class="p">}</span>
</code></pre></div></div>
<p>Recently (since 2.3.7) we’ve added an alternative way of Jackson integration using builder. It works when you point <code class="language-plaintext highlighter-rouge">@JsonDeserialize(builder)</code> to a generated or “extending” builder. The example will make it clear:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Style</span><span class="o">(</span><span class="n">builder</span> <span class="o">=</span> <span class="s">"new"</span><span class="o">)</span> <span class="c1">// builder has to have constructor</span>
<span class="nd">@JsonDeserialize</span><span class="o">(</span><span class="n">builder</span> <span class="o">=</span> <span class="nc">ImmutableVal</span><span class="o">.</span><span class="na">Builder</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="kd">interface</span> <span class="nc">Val</span> <span class="o">{</span>
<span class="kt">int</span> <span class="nf">a</span><span class="o">();</span>
<span class="nd">@JsonProperty</span><span class="o">(</span><span class="s">"b"</span><span class="o">)</span> <span class="nc">String</span> <span class="nf">second</span><span class="o">();</span>
<span class="o">}</span>
<span class="c1">// or using extending builder</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="nd">@JsonDeserialize</span><span class="o">(</span><span class="n">builder</span> <span class="o">=</span> <span class="nc">Val</span><span class="o">.</span><span class="na">Builder</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="kd">interface</span> <span class="nc">Val</span> <span class="o">{</span>
<span class="kt">int</span> <span class="nf">a</span><span class="o">();</span>
<span class="nd">@JsonProperty</span><span class="o">(</span><span class="s">"b"</span><span class="o">)</span> <span class="nc">String</span> <span class="nf">second</span><span class="o">();</span>
<span class="kd">class</span> <span class="nc">Builder</span> <span class="kd">extends</span> <span class="nc">ImmutableVal</span><span class="o">.</span><span class="na">Builder</span> <span class="o">{}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Using the approach shown above, generated builders will have attributes annotated with <code class="language-plaintext highlighter-rouge">@JsonProperty</code> so deserialization will work properly.</p>
<p><strong>Things to be aware of</strong></p>
<ul>
<li>Make sure that <em>Jackson</em> can serialize any other type that is used as attribute type.</li>
<li>Not all Jackson annotations are propagated by default to the generated code. You can use <code class="language-plaintext highlighter-rouge">Value.Style.additionalJsonAnnotations</code> style attribute to specify such annotation types.</li>
<li>If using <code class="language-plaintext highlighter-rouge">@JsonIgnore</code>, you should explicitly make an attribute non-mandatory. In Immutables, an attribute can be declared as non-mandatory via <code class="language-plaintext highlighter-rouge">@Nullable</code>, <code class="language-plaintext highlighter-rouge">Optional</code> or <code class="language-plaintext highlighter-rouge">@Value.Default</code> which are all different in their effect and we do not derive anything automatically.</li>
<li>Use <code class="language-plaintext highlighter-rouge">Value.Style.jacksonIntegration = false</code> (since 2.3.7) to disable any out-of-the-box integration triggered <code class="language-plaintext highlighter-rouge">@JsonSerialize</code>/<code class="language-plaintext highlighter-rouge">@JsonDeserialize</code>, may help if integration is getting in the way</li>
<li>Use <code class="language-plaintext highlighter-rouge">Value.Style.forceJacksonPropertyNames = false</code> to not use literal names in generated <code class="language-plaintext highlighter-rouge">@JsonProperty</code> annotations. While somewhat fragile, an absence of the literal names enables the usage of naming strategies and built-in Jackson conventions.</li>
</ul>
<h3 id="jackson-guava">Jackson-Guava</h3>
<p>If you use Guava, make sure to use the special serialization module <code class="language-plaintext highlighter-rouge">jackson-datatype-guava</code>.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><dependency></span>
<span class="nt"><groupId></span>com.fasterxml.jackson.datatype<span class="nt"></groupId></span>
<span class="nt"><artifactId></span>jackson-datatype-guava<span class="nt"></artifactId></span>
<span class="nt"><version></span>2.4.0<span class="nt"></version></span>
<span class="nt"></dependency></span>
</code></pre></div></div>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="nc">ObjectMapper</span> <span class="n">mapper</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ObjectMapper</span><span class="o">();</span>
<span class="c1">// register module with object mapper</span>
<span class="n">mapper</span><span class="o">.</span><span class="na">registerModule</span><span class="o">(</span><span class="k">new</span> <span class="nc">GuavaModule</span><span class="o">());</span>
</code></pre></div></div>
<h3 id="jackson-and-java-8">Jackson and Java 8</h3>
<p>For Java 8 specific datatypes use <code class="language-plaintext highlighter-rouge">jackson-datatype-jdk8</code> module.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><dependency></span>
<span class="nt"><groupId></span>com.fasterxml.jackson.datatype<span class="nt"></groupId></span>
<span class="nt"><artifactId></span>jackson-datatype-jdk8<span class="nt"></artifactId></span>
<span class="nt"><version></span>2.6.3<span class="nt"></version></span>
<span class="nt"></dependency></span>
</code></pre></div></div>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">ObjectMapper</span> <span class="n">mapper</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ObjectMapper</span><span class="o">();</span>
<span class="n">mapper</span><span class="o">.</span><span class="na">registerModule</span><span class="o">(</span><span class="k">new</span> <span class="nc">Jdk8Module</span><span class="o">());</span>
</code></pre></div></div>
<p>Sometimes you might use high-level application framework which handles <em>Jackson</em> for you. So in order to register modules you need to get to <code class="language-plaintext highlighter-rouge">ObjectMapper</code> during initialization phase and configure it. Here’s the sample of how it looks like for <em>Dropwizard</em></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">(</span><span class="nc">AppConfiguration</span> <span class="n">configuration</span><span class="o">,</span> <span class="nc">Environment</span> <span class="n">environment</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
<span class="n">environment</span><span class="o">.</span><span class="na">getObjectMapper</span><span class="o">().</span><span class="na">registerModule</span><span class="o">(</span><span class="k">new</span> <span class="nc">GuavaModule</span><span class="o">());</span>
<span class="n">environment</span><span class="o">.</span><span class="na">getObjectMapper</span><span class="o">().</span><span class="na">registerModule</span><span class="o">(</span><span class="k">new</span> <span class="nc">Jdk8Module</span><span class="o">());</span>
<span class="o">...</span>
<span class="o">}</span>
</code></pre></div></div>
<h3 id="reducing-annotation-clutter">Reducing annotation clutter</h3>
<p>You can find some number of examples using <em>Immutables</em> and <em>Jackson</em> where annotations are cluttering definitions, annotations are piling on top of each other in many levels. But there are ways to significantly reduce annotation noise. Firstly, if using meta-annotated <a href="/style.html">custom style</a> annotation, you can move it to top level class, package (in corresponding <code class="language-plaintext highlighter-rouge">pacakge-info.java</code> file) or even parent package. Secondly, if you mostly use generated value type, rather that abstract value type, you don’t need specify <code class="language-plaintext highlighter-rouge">@JsonDeserialize(as = ImmutableForEverySingleValue.class)</code>, you can put <code class="language-plaintext highlighter-rouge">@JsonSerialize</code> as meta-annotation as with style annotation, and you can put custom (meta-annotated) annotation and put it on a type or a package.</p>
<p>Here’s modified example taken from <em>Lagom Framework</em> documentation <a href="http://www.lagomframework.com/documentation/1.0.x/Immutable.html#Example-of-PersistentEntity-Events">Immutable.html page</a>.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@JsonSerialize</span> <span class="c1">// Jackson automatic integration, why not?</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Style</span><span class="o">(</span>
<span class="n">typeAbstract</span> <span class="o">=</span> <span class="s">"Abstract*"</span><span class="o">,</span>
<span class="n">typeImmutable</span> <span class="o">=</span> <span class="s">"*"</span><span class="o">,</span>
<span class="n">visibility</span> <span class="o">=</span> <span class="nc">ImplementationVisibility</span><span class="o">.</span><span class="na">PUBLIC</span><span class="o">)</span>
<span class="nd">@interface</span> <span class="nc">MyStyle</span> <span class="o">{}</span> <span class="c1">// Custom style</span>
<span class="c1">// ...</span>
<span class="nd">@MyStyle</span> <span class="c1">//<-- Meta annotated with @JsonSerialize and @Value.Style</span>
<span class="c1">// and applies to nested immutable objects</span>
<span class="kd">interface</span> <span class="nc">BlogEvent</span> <span class="kd">extends</span> <span class="nc">Jsonable</span> <span class="o">{</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span> <span class="c1">// <-- looks a lot cleaner, 1 annotation instead of 3</span>
<span class="kd">interface</span> <span class="nc">AbstractPostAdded</span> <span class="kd">extends</span> <span class="nc">BlogEvent</span> <span class="o">{</span>
<span class="nc">String</span> <span class="nf">getPostId</span><span class="o">();</span>
<span class="nc">BodyChanged</span> <span class="nf">getContent</span><span class="o">();</span>
<span class="o">}</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="kd">interface</span> <span class="nc">AbstractBodyChanged</span> <span class="kd">extends</span> <span class="nc">BlogEvent</span> <span class="o">{</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Parameter</span>
<span class="nc">String</span> <span class="nf">getBody</span><span class="o">();</span>
<span class="o">}</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="kd">interface</span> <span class="nc">AbstractPostPublished</span> <span class="kd">extends</span> <span class="nc">BlogEvent</span> <span class="o">{</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Parameter</span>
<span class="nc">String</span> <span class="nf">getPostId</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<hr />
<p><a name="gson"></a>
Gson
—-</p>
<h3 id="dependencies">Dependencies</h3>
<ul>
<li><a href="https://search.maven.org/artifact/org.immutables/value/2.10.1/jar">org.immutables:value:2.10.1</a></li>
<li><a href="https://search.maven.org/artifact/org.immutables/gson/2.10.1/jar">org.immutables:gson:2.10.1</a></li>
</ul>
<p>Gson integration requires the <code class="language-plaintext highlighter-rouge">com.google.gson:gson</code> compile and runtime modules.
The <code class="language-plaintext highlighter-rouge">org.immutables:gson</code> module contains compile-time annotations to generate <code class="language-plaintext highlighter-rouge">TypeAdapter</code> factories.
Optionally, the <code class="language-plaintext highlighter-rouge">org.immutables:gson</code> module can also be used at runtime to enable the following functionality:</p>
<ul>
<li><a href="#field-naming-strategy">Field naming strategy support</a></li>
<li><a href="#poly">Polymorphic serialization by structure</a></li>
<li><a href="#gson-jackson">Gson to Jackson streaming bridge</a></li>
</ul>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><dependency></span>
<span class="nt"><groupId></span>org.immutables<span class="nt"></groupId></span>
<span class="nt"><artifactId></span>gson<span class="nt"></artifactId></span>
<span class="nt"><version></span>2.10.1<span class="nt"></version></span>
<span class="c"><!-- If you don't need runtime capabilities - make it compile-only
<scope>provided</scope>--></span>
<span class="nt"></dependency></span>
<span class="nt"><dependency></span>
<span class="nt"><groupId></span>org.immutables<span class="nt"></groupId></span>
<span class="nt"><artifactId></span>value<span class="nt"></artifactId></span>
<span class="nt"><version></span>2.10.1<span class="nt"></version></span>
<span class="nt"><scope></span>provided<span class="nt"></scope></span>
<span class="nt"></dependency></span>
</code></pre></div></div>
<p><strong>Can’t wait to see generated code?</strong></p>
<ul>
<li>See the <a href="/typeadapters.html">generated code sample</a></li>
</ul>
<h3 id="generating-type-adapters">Generating Type Adapters</h3>
<p>Use the annotation <code class="language-plaintext highlighter-rouge">@org.immutables.gson.Gson.TypeAdapters</code> to generate a <code class="language-plaintext highlighter-rouge">TypeAdapaterFactory</code>
implementation which produces adapters to any immutable classes enclosed by
<code class="language-plaintext highlighter-rouge">@Gson.TypeAdapters</code> annotations. The annotation can be placed on top-level type or package
(using <code class="language-plaintext highlighter-rouge">package-info.java</code>). The type adapter factory will support all immutable classes in
the corresponding type (directly annotated and all nested immutable values) or package. A
class named <code class="language-plaintext highlighter-rouge">GsonAdapters[NameOfAnnotatedElement]</code> will be generated in the same package.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// generated GsonAdaptersAdapt factory will handle all immutable types here:</span>
<span class="c1">// Adapt, Inr, Nst</span>
<span class="nd">@Gson</span><span class="o">.</span><span class="na">TypeAdapters</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">Adapt</span> <span class="o">{</span>
<span class="kt">long</span> <span class="nf">id</span><span class="o">();</span>
<span class="nc">Optional</span><span class="o"><</span><span class="nc">String</span><span class="o">></span> <span class="nf">description</span><span class="o">();</span>
<span class="nc">Set</span><span class="o"><</span><span class="nc">Inr</span><span class="o">></span> <span class="nf">set</span><span class="o">();</span>
<span class="nc">Multiset</span><span class="o"><</span><span class="nc">Nst</span><span class="o">></span> <span class="nf">bag</span><span class="o">();</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">Inr</span> <span class="o">{</span>
<span class="kt">int</span><span class="o">[]</span> <span class="nf">arr</span><span class="o">();</span>
<span class="nc">List</span><span class="o"><</span><span class="nc">Integer</span><span class="o">></span> <span class="nf">list</span><span class="o">();</span>
<span class="nc">Map</span><span class="o"><</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Nst</span><span class="o">></span> <span class="nf">map</span><span class="o">();</span>
<span class="nc">SetMultimap</span><span class="o"><</span><span class="nc">Integer</span><span class="o">,</span> <span class="nc">Nst</span><span class="o">></span> <span class="nf">setMultimap</span><span class="o">();</span>
<span class="o">}</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">Nst</span> <span class="o">{</span>
<span class="kt">int</span> <span class="nf">value</span><span class="o">();</span>
<span class="nc">String</span> <span class="nf">string</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<ul>
<li>See javadocs in <a href="https://github.com/immutables/immutables/blob/master/gson/src/org/immutables/gson/Gson.java">Gson</a></li>
</ul>
<p><a name="adapter-registration"></a></p>
<h3 id="type-adapter-registration">Type Adapter registration</h3>
<p>Type adapter factories are generated in the same package and registered statically as service providers in <code class="language-plaintext highlighter-rouge">META-INF/services/com.google.gson.TypeAdapterFactory</code>.
You can manually register factories with <code class="language-plaintext highlighter-rouge">GsonBuilder</code>, but the easiest way to register all such factories is by using <code class="language-plaintext highlighter-rouge">java.util.ServiceLoader</code>:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">com.google.gson.GsonBuilder</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.google.gson.Gson</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.google.gson.TypeAdapterFactory</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.ServiceLoader</span><span class="o">;</span>
<span class="o">...</span>
<span class="nc">GsonBuilder</span> <span class="n">gsonBuilder</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">GsonBuilder</span><span class="o">();</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">TypeAdapterFactory</span> <span class="n">factory</span> <span class="o">:</span> <span class="nc">ServiceLoader</span><span class="o">.</span><span class="na">load</span><span class="o">(</span><span class="nc">TypeAdapterFactory</span><span class="o">.</span><span class="na">class</span><span class="o">))</span> <span class="o">{</span>
<span class="n">gsonBuilder</span><span class="o">.</span><span class="na">registerTypeAdapterFactory</span><span class="o">(</span><span class="n">factory</span><span class="o">);</span>
<span class="o">}</span>
<span class="c1">// Manual registration is also an option</span>
<span class="n">gsonBuilder</span><span class="o">.</span><span class="na">registerTypeAdapterFactory</span><span class="o">(</span><span class="k">new</span> <span class="nc">GsonAdaptersMyDocument</span><span class="o">());</span>
<span class="nc">Gson</span> <span class="n">gson</span> <span class="o">=</span> <span class="n">gsonBuilder</span><span class="o">.</span><span class="na">create</span><span class="o">();</span>
<span class="nc">String</span> <span class="n">json</span> <span class="o">=</span> <span class="n">gson</span><span class="o">.</span><span class="na">toJson</span><span class="o">(</span>
<span class="nc">ImmutableValueObject</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">id</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
<span class="o">.</span><span class="na">name</span><span class="o">(</span><span class="s">"A"</span><span class="o">)</span>
<span class="o">.</span><span class="na">build</span><span class="o">());</span>
<span class="c1">// { "id": 1, "name": "A" }</span>
</code></pre></div></div>
<p><strong>Things to be aware of</strong></p>
<ul>
<li>When type adapters are not registered, Gson will use default reflective serializer. However, it will fail to deserialize!</li>
<li>There’s the potential to confuse the <code class="language-plaintext highlighter-rouge">com.google.gson.Gson</code> object with the <code class="language-plaintext highlighter-rouge">@org.immutable.gson.Gson</code> umbrella annotation, but they are usually not used together in the same source file. If this will be huge PITA, please let us know!</li>
</ul>
<h3 id="jax-rs-integration">JAX-RS integration</h3>
<p>A JAX-RS message body reader/writer is provided out of the box. In itself it is a generic Gson integration provider, but it has following special capabilities:</p>
<ul>
<li>Auto registration of Gson type adapter factories from <code class="language-plaintext highlighter-rouge">META-INF/services/com.google.gson.TypeAdapterFactory</code>.</li>
<li>Built in support for <a href="#gson-jackson">Gson-Jackson</a> bridge. It is turned on by default if the <em>Jackson</em> library is in the classpath at runtime.</li>
</ul>
<p>To use immutable types in your JAX-RS services, use
<code class="language-plaintext highlighter-rouge">org.immutables.gson.stream.GsonMessageBodyProvider</code> which implements
<code class="language-plaintext highlighter-rouge">javax.ws.rs.ext.MessageBodyReader</code> and <code class="language-plaintext highlighter-rouge">javax.ws.rs.ext.MessageBodyWriter</code>. Also do not forget
to specify an “application/json” content type, so that the provider will match.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Contrived illustration for marshaling of immutable abstract types: InputValue and OutputValue</span>
<span class="c1">// using GsonMessageBodyProvider</span>
<span class="nd">@Path</span><span class="o">(</span><span class="s">"/test"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">TestResource</span> <span class="o">{</span>
<span class="nd">@POST</span>
<span class="nd">@Consumes</span><span class="o">(</span><span class="nc">MediaType</span><span class="o">.</span><span class="na">APPLICATION_JSON</span><span class="o">)</span>
<span class="nd">@Produces</span><span class="o">(</span><span class="nc">MediaType</span><span class="o">.</span><span class="na">APPLICATION_JSON</span><span class="o">)</span>
<span class="kd">public</span> <span class="nc">OutputValue</span> <span class="nf">post</span><span class="o">(</span><span class="nc">InputValue</span> <span class="n">input</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">val</span> <span class="o">=</span> <span class="n">input</span><span class="o">.</span><span class="na">inputAttribute</span><span class="o">();</span>
<span class="k">return</span> <span class="nc">ImmutableOutputValue</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">outputAttribute</span><span class="o">(</span><span class="n">val</span><span class="o">);</span>
<span class="o">.</span><span class="na">build</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">...</span>
<span class="o">}</span>
</code></pre></div></div>
<p>While this provider can be picked up automatically from the classpath using <code class="language-plaintext highlighter-rouge">META-INF/services/javax.ws.rs.ext.*</code> by the JAX-RS engine, sometimes you’ll need to add it manually.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Dropwizard Application example</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">(</span><span class="nc">DwConfiguration</span> <span class="n">configuration</span><span class="o">,</span> <span class="nc">Environment</span> <span class="n">environment</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
<span class="n">environment</span><span class="o">.</span><span class="na">jersey</span><span class="o">().</span><span class="na">register</span><span class="o">(</span><span class="k">new</span> <span class="nc">TestResource</span><span class="o">());</span>
<span class="n">environment</span><span class="o">.</span><span class="na">jersey</span><span class="o">().</span><span class="na">register</span><span class="o">(</span><span class="k">new</span> <span class="nc">GsonMessageBodyProvider</span><span class="o">());</span>
<span class="o">}</span>
</code></pre></div></div>
<p>You can create a customized <code class="language-plaintext highlighter-rouge">GsonMessageBodyProvider</code> instance:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">new</span> <span class="nc">GsonMessageBodyProvider</span><span class="o">(</span>
<span class="k">new</span> <span class="nf">GsonProviderOptionsBuilder</span><span class="o">()</span>
<span class="o">.</span><span class="na">gson</span><span class="o">(</span><span class="k">new</span> <span class="nc">Gson</span><span class="o">())</span> <span class="c1">// build custom Gson instance using GsonBuilder methods</span>
<span class="o">.</span><span class="na">addMediaTypes</span><span class="o">(</span><span class="nc">MediaType</span><span class="o">.</span><span class="na">TEXT_PLAIN_TYPE</span><span class="o">)</span> <span class="c1">// specify custom media types</span>
<span class="o">.</span><span class="na">allowJackson</span><span class="o">(</span><span class="kc">false</span><span class="o">)</span> <span class="c1">// you can switch off Gson-Jackson bridge</span>
<span class="o">.</span><span class="na">lenient</span><span class="o">(</span><span class="kc">true</span><span class="o">)</span> <span class="c1">// you can enable non-strict mode</span>
<span class="o">.</span><span class="na">build</span><span class="o">())</span> <span class="o">{</span>
<span class="c1">// Some JAX-RS implementations (Jersey) track message body providers by class identity,</span>
<span class="c1">// Anonymous class could be defined to create unique class.</span>
<span class="c1">// It allows to register couple of GsonMessageBodyProvider with different configuration</span>
<span class="c1">// by having unique classes.</span>
<span class="o">};</span>
</code></pre></div></div>
<ul>
<li>See class <a href="https://github.com/immutables/immutables/blob/master/gson/src/org/immutables/gson/stream/GsonMessageBodyProvider.java">GsonMessageBodyProvider</a></li>
</ul>
<h3 id="mapping-features">Mapping Features</h3>
<p>Automatically generated bindings are straightforward and generally useful.</p>
<ul>
<li>Java primitives and Strings — work as built-in types</li>
<li>Nested documents/objects - supported as long as corresponding type adapter would be registered with Gson</li>
<li>Lists, Sets, Maps, Optional and other supported containers of the above types:
<ul>
<li>Collections mapped to JSON arrays</li>
<li>Map and Multimaps mapped to JSON object (keys always converted to strings)</li>
<li>Optional attributes - as nullable fields</li>
</ul>
</li>
<li>Immutable values having only constructor - arrays of constructor arguments.</li>
</ul>
<p>While there’s certain amount of customization (like changing field names in JSON), the basic idea is
to have direct and straightforward mappings to JSON derived from the structure of value objects,
where value objects are adapted to a representation rather than free-form objects having complex
mappings to JSON representations.</p>
<p>To add custom binding for types, other than immutable values, use Gson APIs. Please refer to <a href="https://sites.google.com/site/gson/gson-user-guide#TOC-Custom-Serialization-and-Deserialization">Gson reference</a></p>
<h4 id="generic-parameters">Generic parameters</h4>
<p>Generic parameters are supported when some upper level JSON document object specify actual type parameters, so nested document value objects that are parametrized may know exact type used in the context.</p>
<p>Let’s say you have value type <code class="language-plaintext highlighter-rouge">Val</code> with the following definition.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Gson</span><span class="o">.</span><span class="na">TypeAdapters</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="kd">interface</span> <span class="nc">Val</span><span class="o"><</span><span class="no">T</span><span class="o">></span> <span class="o">{</span>
<span class="no">T</span> <span class="nf">val</span><span class="o">();</span>
<span class="nc">Optional</span><span class="o"><</span><span class="nc">String</span><span class="o">></span> <span class="nf">description</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>
<p>You cannot serialize parametrized type to or from JSON without specifying actual type parameters.
But if we put parametrized type in a context document which provide actual type parameters we can use our generated type adapters for JSON conversion.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Gson</span><span class="o">.</span><span class="na">TypeAdapters</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="kd">interface</span> <span class="nc">Doc</span> <span class="o">{</span>
<span class="nc">Val</span><span class="o"><</span><span class="nc">String</span><span class="o">></span> <span class="nf">str</span><span class="o">();</span> <span class="c1">// actual type T is String</span>
<span class="nc">Val</span><span class="o"><</span><span class="nc">Integer</span><span class="o">></span> <span class="nf">inte</span><span class="o">();</span> <span class="c1">// actual type T is Integer</span>
<span class="nc">Val</span><span class="o"><</span><span class="nc">Boolean</span><span class="o">></span> <span class="nf">bool</span><span class="o">();</span> <span class="c1">// actual type T is Boolean</span>
<span class="o">}</span>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
<span class="dl">"</span><span class="s2">str</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span> <span class="dl">"</span><span class="s2">val</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">StringValue</span><span class="dl">"</span> <span class="p">},</span>
<span class="dl">"</span><span class="s2">ints</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span> <span class="dl">"</span><span class="s2">val</span><span class="dl">"</span><span class="p">:</span> <span class="mi">124</span><span class="p">,</span> <span class="dl">"</span><span class="s2">description</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Just a number</span><span class="dl">"</span> <span class="p">},</span>
<span class="dl">"</span><span class="s2">bool</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span> <span class="dl">"</span><span class="s2">val</span><span class="dl">"</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> <span class="dl">"</span><span class="s2">description</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Just a boolean</span><span class="dl">"</span> <span class="p">},</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Actual type parameters might not only be simple types as string, numbers or booleans, but also nested documents or arrays or the mentioned types.</p>
<p><em>Note: If generic attributes contain comples nested type variables (think <code class="language-plaintext highlighter-rouge">Set<List<T>></code>), then special routines that extract actual type parameters will be referenced in a generated source code, so you will need org.immutable:json artifact packaged as part of your application, not a compile-only dependency</em></p>
<h4 id="field-names">Field names</h4>
<p>By default, the JSON field name is the same as the attribute name.
However, it is very easy to specify the JSON field name as it should appear in the JSON representation.
Use the <code class="language-plaintext highlighter-rouge">value</code> attribute of the <code class="language-plaintext highlighter-rouge">com.google.gson.annotations.SerializedName</code> annotation placed on an attribute accessor.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="nd">@Gson</span><span class="o">.</span><span class="na">TypeAdapters</span>
<span class="kd">public</span> <span class="kd">abstract</span> <span class="kd">class</span> <span class="nc">ValueObject</span> <span class="o">{</span>
<span class="nd">@SerializedName</span><span class="o">(</span><span class="s">"_id"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">abstract</span> <span class="kt">long</span> <span class="nf">getId</span><span class="o">();</span>
<span class="nd">@SerializedName</span><span class="o">(</span><span class="s">"name"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">abstract</span> <span class="nc">String</span> <span class="nf">getNamedAs</span><span class="o">();</span>
<span class="kd">public</span> <span class="kd">abstract</span> <span class="kt">int</span> <span class="nf">getOtherAttribute</span><span class="o">();</span>
<span class="o">}</span>
<span class="nc">ValueObject</span> <span class="n">valueObject</span> <span class="o">=</span>
<span class="nc">ImmutableValueObject</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">id</span><span class="o">(</span><span class="mi">1123</span><span class="o">)</span>
<span class="o">.</span><span class="na">namedAs</span><span class="o">(</span><span class="s">"Valuable One"</span><span class="o">)</span>
<span class="o">.</span><span class="na">otherAttribute</span><span class="o">(</span><span class="mi">0</span><span class="o">)</span>
<span class="o">.</span><span class="na">build</span><span class="o">();</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">valueObject</code> will be marshaled as:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
<span class="dl">"</span><span class="s2">_id</span><span class="dl">"</span><span class="p">:</span> <span class="mi">1123</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">name</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Valuable One</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">otherAttribute</span><span class="dl">"</span><span class="p">:</span> <span class="mi">0</span>
<span class="p">}</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">@Gson.Named</code> is deprecated in favor of <em>Gson</em>’s <code class="language-plaintext highlighter-rouge">SerializedName</code> annotation.
As of <em>Gson</em> v2.5 <code class="language-plaintext highlighter-rouge">SerializedName</code> is applicable to methods and renders <em>Immutables’</em> custom annotation unnecessary. In addition to that, there’s support for <code class="language-plaintext highlighter-rouge">SerializedName.alternate</code> attribute which allows to specify alternative names used during deserialization.</p>
<p><a name="field-naming-strategy"></a>
When running on an Oracle JVM, there’s an option to enable field naming strategy support.
Use <code class="language-plaintext highlighter-rouge">@Gson.TypeAdapters(fieldNamingStrategy = true)</code> to enable generation of code which uses a field naming strategy. See Javadoc for <a href="https://github.com/immutables/immutables/blob/master/gson/src/org/immutables/gson/Gson.java#L78">Gson.TypeAdapters#fieldNamingStrategy</a>.
This feature is not supported on Android and other Java runtimes because of heavy use of reflection hacks to workaround Gson’s limitations to make this work.</p>
<h4 id="ignoring-attributes">Ignoring attributes</h4>
<p>Collection, optional and default attributes can be ignored during marshaling by using <code class="language-plaintext highlighter-rouge">@Gson.Ignore</code> annotation.</p>
<h4 id="omitting-empty-fields">Omitting empty fields</h4>
<p>Use Gson’s configuration <code class="language-plaintext highlighter-rouge">GsonBuilder.serializeNulls()</code> to include empty optional and nullable
fields as <code class="language-plaintext highlighter-rouge">null</code>. By default those will be omitted, this generally helps to keep JSON clean and to
reduce its size if there are a lot of optional attributes. If you want to omit empty collection
attributes in the same way as nullable fields — use <code class="language-plaintext highlighter-rouge">@Gson.TypeAdapters(emptyAsNulls = true)</code></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="nd">@Gson</span><span class="o">.</span><span class="na">TypeAdapters</span><span class="o">(</span><span class="n">emptyAsNulls</span> <span class="o">=</span> <span class="kc">true</span><span class="o">)</span>
<span class="kd">interface</span> <span class="nc">Omits</span> <span class="o">{</span>
<span class="nc">Optional</span><span class="o"><</span><span class="nc">String</span><span class="o">></span> <span class="nf">string</span><span class="o">();</span>
<span class="nc">List</span><span class="o"><</span><span class="nc">String</span><span class="o">></span> <span class="nf">strings</span><span class="o">();</span>
<span class="o">}</span>
<span class="nc">String</span> <span class="n">json</span> <span class="o">=</span> <span class="n">gson</span><span class="o">.</span><span class="na">toJson</span><span class="o">(</span><span class="nc">ImmutableOmits</span><span class="o">.</span><span class="na">builder</span><span class="o">().</span><span class="na">build</span><span class="o">());</span>
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// omits all empty</span>
<span class="p">{</span> <span class="p">}</span>
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// with GsonBuilder.serializeNulls()</span>
<span class="p">{</span> <span class="dl">"</span><span class="s2">string</span><span class="dl">"</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">strings</span><span class="dl">"</span><span class="p">:</span> <span class="p">[]</span> <span class="p">}</span>
</code></pre></div></div>
<h4 id="tuples-of-constructor-arguments">Tuples of constructor arguments</h4>
<p>One of the interesting features of <em>Immutables</em> JSON marshaling is the ability to map tuples
(triples and so on) of constructor arguments. While not universally useful, some data types
could be compactly represented in JSON as array of values. Consider, for example, spatial
coordinates or RGB colors.</p>
<p>In order to marshal object as tuple, you need to annotate <a href="/immutable.html#constructor">constructor</a> arguments and disable generation of <a href="/immutable.html#builder">builders</a>.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span><span class="o">(</span><span class="n">builder</span> <span class="o">=</span> <span class="kc">false</span><span class="o">)</span>
<span class="nd">@Gson</span><span class="o">.</span><span class="na">TypeAdapters</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">Coordinates</span> <span class="o">{</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Parameter</span> <span class="kt">double</span> <span class="nf">latitude</span><span class="o">();</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Parameter</span> <span class="kt">double</span> <span class="nf">longitude</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">...</span>
<span class="nc">Coordinates</span> <span class="n">coordinates</span> <span class="o">=</span> <span class="nc">ImmutableCoordinates</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="mf">37.783333</span><span class="o">,</span> <span class="o">-</span><span class="mf">122.416667</span><span class="o">);</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">coordinates</code> will be marshaled as a JSON array rather than a JSON object</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="mf">37.783333</span><span class="p">,</span> <span class="o">-</span><span class="mf">122.416667</span><span class="p">]</span>
</code></pre></div></div>
<p>A special case of this are values with single constructor parameter.
Having a tuple of 1 argument is essentially equivalent to having just a single argument. Therefore
you can marshal and unmarshal such objects as a value of its single argument.
If you want to make value to be a wrapper type (for the purposes of adding type-safety), but
nevertheless invisible in BSON, you can define it as having no builder and single argument
constructor, so that it will become a pure wrapper:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Gson</span><span class="o">.</span><span class="na">TypeAdapters</span>
<span class="kd">interface</span> <span class="nc">WrapperExample</span> <span class="o">{</span>
<span class="c1">// Name will become wrapper around name string, invisible in JSON</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span><span class="o">(</span><span class="n">builder</span> <span class="o">=</span> <span class="kc">false</span><span class="o">)</span>
<span class="kd">interface</span> <span class="nc">Name</span> <span class="o">{</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Parameter</span> <span class="nc">String</span> <span class="nf">value</span><span class="o">();</span>
<span class="o">}</span>
<span class="c1">// Id will become wrapper around id number, invisible in JSON</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span><span class="o">(</span><span class="n">builder</span> <span class="o">=</span> <span class="kc">false</span><span class="o">)</span>
<span class="kd">interface</span> <span class="nc">Id</span> <span class="o">{</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Parameter</span> <span class="kt">int</span> <span class="nf">value</span><span class="o">();</span>
<span class="o">}</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span><span class="o">(</span><span class="n">builder</span> <span class="o">=</span> <span class="kc">false</span><span class="o">)</span>
<span class="kd">interface</span> <span class="nc">Val</span> <span class="o">{</span>
<span class="nc">Id</span> <span class="nf">id</span><span class="o">();</span>
<span class="nc">Name</span> <span class="nf">name</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="nc">Val</span> <span class="n">val</span> <span class="o">=</span> <span class="nc">ImmutableVal</span><span class="o">.</span><span class="na">build</span><span class="o">()</span>
<span class="o">.</span><span class="na">id</span><span class="o">(</span><span class="nc">ImmutableId</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="mi">124</span><span class="o">))</span>
<span class="o">.</span><span class="na">name</span><span class="o">(</span><span class="nc">ImmutableName</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"Nameless"</span><span class="o">))</span>
<span class="o">.</span><span class="na">build</span><span class="o">();</span>
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
<span class="dl">"</span><span class="s2">id</span><span class="dl">"</span><span class="p">:</span> <span class="mi">124</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">name</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Nameless</span><span class="dl">"</span>
<span class="p">}</span>
</code></pre></div></div>
<p>This makes it possible to achieve the desired level of abstraction and type safety without cluttering JSON data structure.</p>
<p><a name="poly"></a></p>
<h4 id="polymorphic-mapping">Polymorphic mapping</h4>
<p>An interesting feature of <em>Immutables</em> Gson marshaling is the ability to map an abstract type to one of
it’s subclasses by structure as opposed to by a “discriminator” field.</p>
<p>Define a common supertype class and subclasses, then use
<code class="language-plaintext highlighter-rouge">@org.immutables.gson.Gson.ExpectedSubtypes</code> annotation to list the expected subtypes. Then, you
can use a supertype in an attribute as a plain reference or as a collection.</p>
<p><code class="language-plaintext highlighter-rouge">@Gson.ExpectedSubtypes</code> can be placed on:</p>
<ul>
<li>Abstract supertype</li>
<li>Attribute with reference or collection of references to supertype.</li>
</ul>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="nd">@Gson</span><span class="o">.</span><span class="na">TypeAdapters</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">HostDocument</span> <span class="o">{</span>
<span class="c1">// Host document contain list of values</span>
<span class="c1">// @Gson.ExpectedSubtypes annotation could be also placed on attribute.</span>
<span class="nc">List</span><span class="o"><</span><span class="nc">AbstractValue</span><span class="o">></span> <span class="nf">value</span><span class="o">();</span>
<span class="nd">@Gson</span><span class="o">.</span><span class="na">ExpectedSubtypes</span><span class="o">({</span>
<span class="nc">InterestingValue</span><span class="o">.</span><span class="na">class</span><span class="o">,</span>
<span class="nc">RelevantValue</span><span class="o">.</span><span class="na">class</span>
<span class="o">})</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">AbstractValue</span> <span class="o">{}</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">InterestingValue</span> <span class="kd">extends</span> <span class="nc">AbstractValue</span> <span class="o">{</span>
<span class="kt">int</span> <span class="nf">number</span><span class="o">();</span>
<span class="o">}</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">RelevantValue</span> <span class="kd">extends</span> <span class="nc">AbstractValue</span> <span class="o">{</span>
<span class="nc">String</span> <span class="nf">string</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
<span class="dl">"</span><span class="s2">values</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span> <span class="dl">"</span><span class="s2">number</span><span class="dl">"</span><span class="p">:</span> <span class="mi">2</span> <span class="p">},</span>
<span class="p">{</span> <span class="dl">"</span><span class="s2">string</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Relevant?</span><span class="dl">"</span> <span class="p">},</span>
<span class="p">{</span> <span class="dl">"</span><span class="s2">number</span><span class="dl">"</span><span class="p">:</span> <span class="mi">1</span> <span class="p">},</span>
<span class="p">]</span>
<span class="p">}</span>
</code></pre></div></div>
<p>As you can guess, the above JSON fragment may be deserialized to <code class="language-plaintext highlighter-rouge">HostDocument</code>, the <code class="language-plaintext highlighter-rouge">value</code>
attribute of which will contain instances of <code class="language-plaintext highlighter-rouge">InterestingValue</code>, followed by <code class="language-plaintext highlighter-rouge">RelevantValue</code>,
and finally <code class="language-plaintext highlighter-rouge">InterestingValue</code>.</p>
<p>In addition, when using a value <a href="/style.html#nesting">nested in enclosing</a>, the exact set of
subclasses can be figured out from the set of nested types in the enclosing scope. In that case,
the <code class="language-plaintext highlighter-rouge">@Gson.ExpectedSubtypes</code> annotation may have its “value” attribute omitted.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Gson</span><span class="o">.</span><span class="na">TypeAdapters</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Enclosing</span>
<span class="kd">interface</span> <span class="nc">Enc</span> <span class="o">{</span>
<span class="kd">interface</span> <span class="nc">A</span> <span class="o">{}</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span> <span class="kd">interface</span> <span class="nc">B</span> <span class="kd">extends</span> <span class="no">A</span> <span class="o">{</span> <span class="kt">int</span> <span class="nf">b</span><span class="o">();</span> <span class="o">}</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span> <span class="kd">interface</span> <span class="nc">C</span> <span class="kd">extends</span> <span class="no">A</span> <span class="o">{</span> <span class="kt">double</span> <span class="nf">c</span><span class="o">();</span> <span class="o">}</span>
<span class="nd">@Value</span><span class="o">.</span><span class="na">Immutable</span> <span class="kd">interface</span> <span class="nc">E</span> <span class="o">{</span>
<span class="nd">@Gson</span><span class="o">.</span><span class="na">ExpectedSubtypes</span> <span class="no">A</span> <span class="nf">a</span><span class="o">();</span> <span class="c1">// B and C will be discovered</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Although a nice feature, you should generally avoid the use of polymorphic marshaling if performance is
important. Current implementation may suffer JIT deoptimizations due to exceptions being thrown
and caught during regular deserialization. This renders the polymorphic deserialization feature
useful for auxiliary uses (such as configuration or model serialization), but less useful for
high-throughput document streaming. However, the implementation can be changed (improved) in future.</p>
<p><strong>Things to be aware of</strong></p>
<ul>
<li>If none of expected subclasses matches the structure of the JSON, a <code class="language-plaintext highlighter-rouge">RuntimeException</code>s is thrown during deserialization</li>
<li>If subclass structures have a collision, the first matching type wins</li>
<li>Run-time performance</li>
</ul>
<p><a name="gson-jackson"></a></p>
<h3 id="gson-jackson-bridge">Gson-Jackson bridge</h3>
<p>We can push <em>Gson</em>’s performance to its limits by delegating low-level streaming to
<em>Jackson</em>. <em>Gson</em> is pretty optimized in itself, but <em>Jackson</em> is playing an “unfair game”
by optimizing the whole chain of JSON streaming, including UTF-8 encoding handling, recycling
of special buffers, DIY number parsing and formatting etc. This can be as much as 200% faster
for some workloads.</p>
<p>There’s sample benchmark which we used only to see relative difference. As usual, take those
numbers with a grain of salt: it’s just some numbers for some JSON documents on some MacBook.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Benchmark Mode Samples Score Error Units
o.i.s.j.JsonBenchmarks.autoJackson avgt 5 709.249 ± 19.170 us/op
o.i.s.j.JsonBenchmarks.immutablesGson avgt 5 1155.550 ± 48.843 us/op
o.i.s.j.JsonBenchmarks.immutablesGsonJackson avgt 5 682.605 ± 20.839 us/op
o.i.s.j.JsonBenchmarks.pojoGson avgt 5 1402.759 ± 101.077 us/op
o.i.s.j.JsonBenchmarks.pojoGsonJackson avgt 5 935.107 ± 58.210 us/op
o.i.s.j.JsonBenchmarks.pojoJackson avgt 5 721.767 ± 47.782 us/op
</code></pre></div></div>
<p>It is possible use <em>Gson</em> to serialize to and from various additional textual and binary serialization formats supported by <em>Jackson</em>:</p>
<p><a href="https://github.com/FasterXML/jackson-dataformat-smile">Smile</a>,
<a href="https://github.com/michel-kraemer/bson4jackson">BSON</a>,
<a href="https://github.com/FasterXML/jackson-dataformat-cbor">CBOR</a>,
<a href="https://github.com/FasterXML/jackson-dataformat-yaml">YAML</a>… etc.</p>
<ul>
<li>JAX-RS provider also integrates Gson-Jackson bridge out of the box. Use it as an example of how to integrate Gson-Jackson bridge.</li>
<li>See class <a href="https://github.com/immutables/immutables/blob/master/gson/src/org/immutables/gson/stream/JsonGeneratorWriter.java">JsonGeneratorWriter</a></li>
<li>See class <a href="https://github.com/immutables/immutables/blob/master/gson/src/org/immutables/gson/stream/JsonParserReader.java">JsonParserReader</a></li>
<li>See sample <a href="https://github.com/immutables/samples/tree/master/json/src/org/immutables/samples/json">benchmark code</a></li>
</ul>
</section>
<footer class="jumbotron">
<div class="container">
<h2 id="guides">Guides</h2>
<ul>
<li><a href="/getstarted.html">Get started!</a></li>
<li><a href="/intro.html">Inception</a></li>
<li><a href="/immutable.html">Immutable objects</a></li>
<li><a href="/factory.html">Factory builders</a></li>
<li><a href="/functional.html">Functions and Predicates (for Java 7)</a></li>
<li><a href="/style.html">Style customization</a></li>
<li><a href="/json.html">JSON serialization</a></li>
<li><a href="/criteria.html">Criteria</a></li>
<li><a href="/mongo.html">MongoDB repositories</a></li>
<li><a href="/dynamodb.html">DynamoDB integration</a></li>
<li><a href="/encoding.html">Encoding: Customizing attributes and builders (experimental)</a></li>
<li><a href="/apt.html">Using annotation processor in IDE</a></li>
</ul>
<h2 id="get-involved">Get involved</h2>
<ul>
<li>Clone source repository, contribute bug reports and fixes on <a href="https://github.com/immutables/immutables">GitHub immutables/immutables</a></li>
<li>Issue reports, questions and feedback is welcome on issue tracker <a href="https://github.com/immutables/immutables/issues">GitHub immutables/immutables/issues</a></li>
<li>News and announcements on twitter <a href="https://twitter.com/ImmutablesOrg">@ImmutablesOrg</a></li>
</ul>
<p><a href="/license.html">Apache License 2.0</a></p>
<!--<div><h2>Posts</h2>
<ul>
</ul>
</div>-->
</div>
</footer>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script defer src="/gfx/jquery.toc.min.js"></script>
<script>
$(function() {
$('#toc').toc({
container: '.documentation',
selectors: 'h1,h2,h3,h4',
anchorName: function(i, heading, prefix) {
heading = $(heading).text();
if (heading.trim) heading = heading.trim();
return heading.toLowerCase().replace(/ /g, '-').replace(/[^a-z^\-]+/g, '');
},
})
})
</script>
</body>
</html>