1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.lang3.builder;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertThrows;
21
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.Date;
26 import java.util.HashMap;
27 import java.util.LinkedHashMap;
28 import java.util.List;
29 import java.util.Map;
30
31 import org.apache.commons.lang3.AbstractLangTest;
32 import org.apache.commons.lang3.builder.ToStringStyleTest.Person;
33 import org.junit.jupiter.api.AfterEach;
34 import org.junit.jupiter.api.BeforeEach;
35 import org.junit.jupiter.api.Test;
36
37
38
39
40 public class JsonToStringStyleTest extends AbstractLangTest {
41
42 static class AcademyClass {
43 Teacher teacher;
44 List<Student> students;
45
46 public List<Student> getStudents() {
47 return students;
48 }
49
50 public Teacher getTeacher() {
51 return teacher;
52 }
53
54 public void setStudents(final List<Student> students) {
55 this.students = students;
56 }
57
58 public void setTeacher(final Teacher teacher) {
59 this.teacher = teacher;
60 }
61
62 @Override
63 public String toString() {
64 return ToStringBuilder.reflectionToString(this);
65 }
66 }
67
68 enum EmptyEnum {
69 }
70
71 enum Hobby {
72 SPORT,
73 BOOK,
74 MUSIC
75 }
76
77
78
79
80 static class InnerMapObject {
81
82
83
84 String pid;
85
86
87
88
89 Map<String, Object> map;
90 }
91
92
93
94
95 static class NestingPerson {
96
97
98
99 String pid;
100
101
102
103
104 Person person;
105 }
106
107 static class Student {
108 List<Hobby> hobbies;
109
110 public List<Hobby> getHobbies() {
111 return hobbies;
112 }
113
114 public void setHobbies(final List<Hobby> hobbies) {
115 this.hobbies = hobbies;
116 }
117
118 @Override
119 public String toString() {
120 return ToStringBuilder.reflectionToString(this);
121 }
122 }
123
124 static class Teacher {
125 Hobby[] hobbies;
126
127 public Hobby[] getHobbies() {
128 return hobbies;
129 }
130
131 public void setHobbies(final Hobby[] hobbies) {
132 this.hobbies = hobbies;
133 }
134
135 @Override
136 public String toString() {
137 return ToStringBuilder.reflectionToString(this);
138 }
139 }
140
141 private final Integer base = Integer.valueOf(5);
142
143 @BeforeEach
144 public void setUp() {
145 ToStringBuilder.setDefaultStyle(ToStringStyle.JSON_STYLE);
146 }
147
148 @AfterEach
149 public void tearDown() {
150 ToStringBuilder.setDefaultStyle(ToStringStyle.DEFAULT_STYLE);
151 }
152
153 @Test
154 public void testAppendSuper() {
155 assertEquals(
156 "{}",
157 new ToStringBuilder(base).appendSuper(
158 "Integer@8888[" + System.lineSeparator() + "]")
159 .toString());
160 assertEquals(
161 "{}",
162 new ToStringBuilder(base).appendSuper(
163 "Integer@8888[" + System.lineSeparator() + " null"
164 + System.lineSeparator() + "]").toString());
165 assertEquals(
166 "{\"a\":\"hello\"}",
167 new ToStringBuilder(base)
168 .appendSuper(
169 "Integer@8888[" + System.lineSeparator()
170 + "]").append("a", "hello").toString());
171 assertEquals(
172 "{\"a\":\"hello\"}",
173 new ToStringBuilder(base)
174 .appendSuper(
175 "Integer@8888[" + System.lineSeparator()
176 + " null" + System.lineSeparator()
177 + "]").append("a", "hello").toString());
178 assertEquals("{\"a\":\"hello\"}", new ToStringBuilder(base)
179 .appendSuper(null).append("a", "hello").toString());
180
181 assertEquals("{\"a\":\"hello\",\"b\":\"world\"}", new ToStringBuilder(base)
182 .appendSuper("{\"a\":\"hello\"}").append("b", "world").toString());
183 }
184
185 @Test
186 public void testArray() {
187 final Person p = new Person();
188 p.name = "Jane Doe";
189 p.age = 25;
190 p.smoker = true;
191
192 assertEquals(
193 "{\"name\":\"Jane Doe\",\"age\":25,\"smoker\":true,\"groups\":['admin', 'manager', 'user']}",
194 new ToStringBuilder(p).append("name", p.name)
195 .append("age", p.age).append("smoker", p.smoker)
196 .append("groups", new Object() {
197 @Override
198 public String toString() {
199 return "['admin', 'manager', 'user']";
200 }
201 })
202 .toString());
203 }
204
205 @Test
206 public void testArrayEnum() {
207 final Teacher teacher = new Teacher();
208 final Hobby[] hobbies = new Hobby[3];
209 hobbies[0] = Hobby.BOOK;
210 hobbies[1] = Hobby.SPORT;
211 hobbies[2] = Hobby.MUSIC;
212
213 teacher.setHobbies(hobbies);
214
215 assertEquals(teacher.toString(), "{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}");
216 teacher.setHobbies(new Hobby[0]);
217 assertEquals(teacher.toString(), "{\"hobbies\":[]}");
218 teacher.setHobbies(null);
219 assertEquals(teacher.toString(), "{\"hobbies\":null}");
220 }
221
222 @Test
223 public void testBlank() {
224 assertEquals("{}", new ToStringBuilder(base).toString());
225 }
226
227 @Test
228 public void testBooleanArray() {
229 final boolean[] array = {true, false};
230
231 final ToStringBuilder toStringBuilder = new ToStringBuilder(base);
232 assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString());
233
234 assertEquals("{\"booleanArray\":[true,false]}", toStringBuilder.append("booleanArray", array)
235 .toString());
236
237 assertThrows(
238 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
239
240 assertThrows(
241 UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString());
242
243 assertThrows(
244 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
245 }
246
247 @Test
248 public void testByteArray() {
249 final byte[] array = {1, 2, -3, 4};
250
251 final ToStringBuilder toStringBuilder = new ToStringBuilder(base);
252 assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString());
253
254 assertEquals("{\"byteArray\":[1,2,-3,4]}", toStringBuilder.append("byteArray", array)
255 .toString());
256
257 assertThrows(
258 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
259
260 assertThrows(
261 UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString());
262
263 assertThrows(
264 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
265 }
266
267 @Test
268 public void testChar() {
269 assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append('A').toString());
270
271 assertEquals("{\"a\":\"A\"}", new ToStringBuilder(base).append("a", 'A')
272 .toString());
273 assertEquals("{\"a\":\"A\",\"b\":\"B\"}", new ToStringBuilder(base).append("a", 'A').append("b", 'B')
274 .toString());
275 }
276
277 @Test
278 public void testCharArray() {
279 final char[] array = {'1', '2', '3', '4'};
280
281 final ToStringBuilder toStringBuilder = new ToStringBuilder(base);
282 assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString());
283
284 assertEquals("{\"charArray\":[\"1\",\"2\",\"3\",\"4\"]}", toStringBuilder.append("charArray", array)
285 .toString());
286
287 assertThrows(
288 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
289
290 assertThrows(
291 UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString());
292
293 assertThrows(
294 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
295 }
296
297 @Test
298 public void testCombineListAndEnum() {
299 final Teacher teacher = new Teacher();
300
301 final Hobby[] teacherHobbies = new Hobby[3];
302 teacherHobbies[0] = Hobby.BOOK;
303 teacherHobbies[1] = Hobby.SPORT;
304 teacherHobbies[2] = Hobby.MUSIC;
305
306 teacher.setHobbies(teacherHobbies);
307
308 final Student john = new Student();
309 john.setHobbies(Arrays.asList(Hobby.BOOK, Hobby.MUSIC));
310
311 final Student alice = new Student();
312 alice.setHobbies(new ArrayList<>());
313
314 final Student bob = new Student();
315 bob.setHobbies(Collections.singletonList(Hobby.BOOK));
316
317 final ArrayList<Student> students = new ArrayList<>();
318 students.add(john);
319 students.add(alice);
320 students.add(bob);
321
322 final AcademyClass academyClass = new AcademyClass();
323 academyClass.setStudents(students);
324 academyClass.setTeacher(teacher);
325
326 assertEquals(academyClass.toString(), "{\"students\":[{\"hobbies\":[\"BOOK\",\"MUSIC\"]},{\"hobbies\":[]},{\"hobbies\":[\"BOOK\"]}],\"teacher\":{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}}");
327 }
328
329 @Test
330 public void testDate() {
331 final Date now = new Date();
332 final Date afterNow = new Date(System.currentTimeMillis() + 1);
333
334 assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append(now).toString());
335
336 assertEquals("{\"now\":\"" + now.toString() +"\"}", new ToStringBuilder(base).append("now", now)
337 .toString());
338 assertEquals("{\"now\":\"" + now.toString() +"\",\"after\":\"" + afterNow.toString() + "\"}", new ToStringBuilder(base).append("now", now).append("after", afterNow)
339 .toString());
340 }
341
342 @Test
343 public void testDoubleArray() {
344 final double[] array = {1, 2, -3, 4};
345
346 final ToStringBuilder toStringBuilder = new ToStringBuilder(base);
347 assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString());
348
349 assertEquals("{\"doubleArray\":[1.0,2.0,-3.0,4.0]}", toStringBuilder.append("doubleArray", array)
350 .toString());
351
352 assertThrows(
353 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
354
355 assertThrows(
356 UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString());
357
358 assertThrows(
359 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
360 }
361
362 @Test
363 public void testFloatArray() {
364 final float[] array = {1, 2, -3, 4};
365
366 final ToStringBuilder toStringBuilder = new ToStringBuilder(base);
367 assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString());
368
369 assertEquals("{\"floatArray\":[1.0,2.0,-3.0,4.0]}", toStringBuilder.append("floatArray", array)
370 .toString());
371
372 assertThrows(
373 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
374
375 assertThrows(
376 UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString());
377
378 assertThrows(
379 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
380 }
381
382 @Test
383 public void testIntArray() {
384 final int[] array = {1, 2, -3, 4};
385
386 final ToStringBuilder toStringBuilder = new ToStringBuilder(base);
387 assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString());
388
389 assertEquals("{\"intArray\":[1,2,-3,4]}", toStringBuilder.append("intArray", array)
390 .toString());
391
392 assertThrows(
393 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
394
395 assertThrows(
396 UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString());
397
398 assertThrows(
399 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
400 }
401
402 @Test
403 public void testLANG1395() {
404 assertEquals("{\"name\":\"value\"}", new ToStringBuilder(base).append("name", "value").toString());
405 assertEquals("{\"name\":\"\"}", new ToStringBuilder(base).append("name", "").toString());
406 assertEquals("{\"name\":\"\\\"\"}", new ToStringBuilder(base).append("name", '"').toString());
407 assertEquals("{\"name\":\"\\\\\"}", new ToStringBuilder(base).append("name", '\\').toString());
408 assertEquals("{\"name\":\"Let's \\\"quote\\\" this\"}", new ToStringBuilder(base).append("name", "Let's \"quote\" this").toString());
409 }
410
411 @Test
412 public void testLANG1396() {
413 assertEquals("{\"Let's \\\"quote\\\" this\":\"value\"}", new ToStringBuilder(base).append("Let's \"quote\" this", "value").toString());
414 }
415
416 @Test
417 public void testList() {
418 final Student student = new Student();
419 final ArrayList<Hobby> objects = new ArrayList<>();
420
421 objects.add(Hobby.BOOK);
422 objects.add(Hobby.SPORT);
423 objects.add(Hobby.MUSIC);
424
425 student.setHobbies(objects);
426
427 assertEquals(student.toString(), "{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}");
428 student.setHobbies(new ArrayList<>());
429 assertEquals(student.toString(), "{\"hobbies\":[]}");
430 student.setHobbies(null);
431 assertEquals(student.toString(), "{\"hobbies\":null}");
432 }
433
434 @Test
435 public void testLong() {
436 assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append(3L).toString());
437
438 assertEquals("{\"a\":3}", new ToStringBuilder(base).append("a", 3L)
439 .toString());
440 assertEquals("{\"a\":3,\"b\":4}",
441 new ToStringBuilder(base).append("a", 3L).append("b", 4L)
442 .toString());
443 }
444
445 @Test
446 public void testLongArray() {
447 final long[] array = {1, 2, -3, 4};
448
449 final ToStringBuilder toStringBuilder = new ToStringBuilder(base);
450 assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString());
451
452 assertEquals("{\"longArray\":[1,2,-3,4]}", toStringBuilder.append("longArray", array)
453 .toString());
454
455 assertThrows(
456 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
457
458 assertThrows(
459 UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString());
460
461 assertThrows(
462 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
463 }
464
465 @Test
466 public void testLongArrayArray() {
467 final long[][] array = {{1, 2}, null, {5}};
468
469 final ToStringBuilder toStringBuilder = new ToStringBuilder(base);
470 assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString());
471
472 assertThrows(
473 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
474
475 assertThrows(
476 UnsupportedOperationException.class, () -> toStringBuilder.append((long[][]) null).toString());
477
478 assertThrows(
479 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
480 }
481
482 @Test
483 public void testMapSkipNullKey() {
484 final Map<String, Object> map = new LinkedHashMap<>();
485 map.put("k1", "v1");
486 map.put(null, "v2");
487
488 assertEquals("{\"map\":{\"k1\":\"v1\"}}",
489 new ToStringBuilder(base).append("map", map).toString());
490 }
491
492 @Test
493 public void testNestedMaps() {
494 final Map<String, Object> innerMap = new LinkedHashMap<>();
495 innerMap.put("k2.1", "v2.1");
496 innerMap.put("k2.2", "v2.2");
497 final Map<String, Object> baseMap = new LinkedHashMap<>();
498 baseMap.put("k1", "v1");
499 baseMap.put("k2", innerMap);
500
501 final InnerMapObject object = new InnerMapObject(){
502 @Override
503 public String toString() {
504 return new ToStringBuilder(this).append("pid", this.pid)
505 .append("map", this.map).toString();
506 }
507 };
508 object.pid = "dummy-text";
509 object.map = baseMap;
510
511 assertEquals("{\"object\":{\"pid\":\"dummy-text\",\"map\":{\"k1\":\"v1\"," +
512 "\"k2\":{\"k2.1\":\"v2.1\",\"k2.2\":\"v2.2\"}}}}",
513 new ToStringBuilder(base).append("object", object).toString());
514 }
515
516 @Test
517 public void testNestingPerson() {
518 final Person p = new Person() {
519 @Override
520 public String toString() {
521 return new ToStringBuilder(this).append("name", this.name)
522 .append("age", this.age).append("smoker", this.smoker)
523 .toString();
524 }
525 };
526 p.name = "Jane Doe";
527 p.age = 25;
528 p.smoker = true;
529
530 final NestingPerson nestP = new NestingPerson();
531 nestP.pid="#1@Jane";
532 nestP.person = p;
533
534 assertEquals(
535 "{\"pid\":\"#1@Jane\",\"person\":{\"name\":\"Jane Doe\",\"age\":25,\"smoker\":true}}",
536 new ToStringBuilder(nestP).append("pid", nestP.pid)
537 .append("person", nestP.person)
538 .toString());
539 }
540
541 @Test
542 public void testNull() {
543 assertEquals("null", new ToStringBuilder(null).toString());
544 }
545
546 @Test
547 public void testObject() {
548
549 final Integer i3 = Integer.valueOf(3);
550 final Integer i4 = Integer.valueOf(4);
551
552 assertThrows(
553 UnsupportedOperationException.class, () -> new ToStringBuilder(base).append((Object) null).toString());
554
555 assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append(i3).toString());
556
557 assertEquals("{\"a\":null}",
558 new ToStringBuilder(base).append("a", (Object) null).toString());
559 assertEquals("{\"a\":3}", new ToStringBuilder(base).append("a", i3)
560 .toString());
561 assertEquals("{\"a\":3,\"b\":4}",
562 new ToStringBuilder(base).append("a", i3).append("b", i4)
563 .toString());
564
565 assertThrows(
566 UnsupportedOperationException.class, () -> new ToStringBuilder(base).append("a", i3, false).toString());
567
568 assertThrows(
569 UnsupportedOperationException.class,
570 () -> new ToStringBuilder(base).append("a", new ArrayList<>(), false).toString());
571
572 assertEquals(
573 "{\"a\":[]}",
574 new ToStringBuilder(base).append("a", new ArrayList<>(),
575 true).toString());
576
577 assertThrows(
578 UnsupportedOperationException.class,
579 () -> new ToStringBuilder(base).append("a", new HashMap<>(), false).toString());
580
581 assertEquals(
582 "{\"a\":{}}",
583 new ToStringBuilder(base).append("a",
584 new HashMap<>(), true).toString());
585
586 assertThrows(
587 UnsupportedOperationException.class,
588 () -> new ToStringBuilder(base).append("a", (Object) new String[0], false).toString());
589
590 assertEquals(
591 "{\"a\":[]}",
592 new ToStringBuilder(base).append("a", (Object) new String[0],
593 true).toString());
594
595 assertThrows(
596 UnsupportedOperationException.class,
597 () -> new ToStringBuilder(base).append("a", (Object) new int[]{1, 2, 3}, false).toString());
598
599 assertEquals(
600 "{\"a\":[1,2,3]}",
601 new ToStringBuilder(base).append("a",
602 (Object) new int[]{1, 2, 3}, true).toString());
603
604 assertThrows(
605 UnsupportedOperationException.class,
606 () -> new ToStringBuilder(base).append("a", (Object) new String[]{"v", "x", "y", "z"}, false).toString());
607
608 assertEquals(
609 "{\"a\":[\"v\",\"x\",\"y\",\"z\"]}",
610 new ToStringBuilder(base).append("a",
611 (Object) new String[]{"v", "x", "y", "z"}, true)
612 .toString());
613 }
614
615 @Test
616 public void testObjectArray() {
617 final Object[] array = {null, base, new int[]{3, 6}};
618
619 final ToStringBuilder toStringBuilder = new ToStringBuilder(base);
620 assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString());
621
622 assertEquals("{\"objectArray\":[null,5,[3,6]]}", toStringBuilder.append("objectArray", array)
623 .toString());
624
625 assertThrows(
626 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
627
628 assertThrows(
629 UnsupportedOperationException.class, () -> toStringBuilder.append((Object[]) null).toString());
630
631 assertThrows(
632 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
633 }
634
635 @Test
636 public void testObjectWithInnerMap() {
637 final Map<String, Object> map = new LinkedHashMap<>();
638 map.put("k1", "value1");
639 map.put("k2", 2);
640
641 final InnerMapObject object = new InnerMapObject(){
642 @Override
643 public String toString() {
644 return new ToStringBuilder(this).append("pid", this.pid)
645 .append("map", this.map).toString();
646 }
647 };
648 object.pid = "dummy-text";
649 object.map = map;
650
651 assertEquals("{\"object\":{\"pid\":\"dummy-text\",\"map\":{\"k1\":\"value1\",\"k2\":2}}}",
652 new ToStringBuilder(base).append("object", object).toString());
653 }
654
655 @Test
656 public void testPerson() {
657 final Person p = new Person();
658 p.name = "Jane Doe";
659 p.age = 25;
660 p.smoker = true;
661
662 assertEquals(
663 "{\"name\":\"Jane Doe\",\"age\":25,\"smoker\":true}",
664 new ToStringBuilder(p).append("name", p.name)
665 .append("age", p.age).append("smoker", p.smoker)
666 .toString());
667 }
668
669 @Test
670 public void testRootMap() {
671 final Map<String, Object> map = new LinkedHashMap<>();
672 map.put("k1", "v1");
673 map.put("k2", 2);
674
675 assertEquals("{\"map\":{\"k1\":\"v1\",\"k2\":2}}",
676 new ToStringBuilder(base).append("map", map).toString());
677 }
678
679 @Test
680 public void testShortArray() {
681 final short[] array = {1, 2, -3, 4};
682
683 final ToStringBuilder toStringBuilder = new ToStringBuilder(base);
684 assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString());
685
686 assertEquals("{\"shortArray\":[1,2,-3,4]}", toStringBuilder.append("shortArray", array)
687 .toString());
688
689 assertThrows(
690 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
691
692 assertThrows(
693 UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString());
694
695 assertThrows(
696 UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString());
697 }
698 }