| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.lang3.builder; |
| |
| import static org.junit.jupiter.api.Assertions.assertEquals; |
| import static org.junit.jupiter.api.Assertions.assertThrows; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.commons.lang3.AbstractLangTest; |
| import org.apache.commons.lang3.builder.ToStringStyleTest.Person; |
| import org.junit.jupiter.api.AfterEach; |
| import org.junit.jupiter.api.BeforeEach; |
| import org.junit.jupiter.api.Test; |
| |
| /** |
| * Tests {@link org.apache.commons.lang3.builder.JsonToStringStyleTest}. |
| */ |
| class JsonToStringStyleTest extends AbstractLangTest { |
| |
| static class AcademyClass { |
| Teacher teacher; |
| List<Student> students; |
| |
| public List<Student> getStudents() { |
| return students; |
| } |
| |
| public Teacher getTeacher() { |
| return teacher; |
| } |
| |
| public void setStudents(final List<Student> students) { |
| this.students = students; |
| } |
| |
| public void setTeacher(final Teacher teacher) { |
| this.teacher = teacher; |
| } |
| |
| @Override |
| public String toString() { |
| return ToStringBuilder.reflectionToString(this); |
| } |
| } |
| |
| enum EmptyEnum { |
| } |
| |
| enum Hobby { |
| SPORT, |
| BOOK, |
| MUSIC |
| } |
| |
| /** |
| * An object with a Map field used to test {@code ToStringStyle.JsonToStringStyle}. |
| */ |
| static class InnerMapObject { |
| |
| /** |
| * Test String field. |
| */ |
| String pid; |
| |
| /** |
| * Test inner map field. |
| */ |
| Map<String, Object> map; |
| } |
| |
| /** |
| * An object with nested object structures used to test {@code ToStringStyle.JsonToStringStyle}. |
| */ |
| static class NestingPerson { |
| |
| /** |
| * Test String field. |
| */ |
| String pid; |
| |
| /** |
| * Test nested object field. |
| */ |
| Person person; |
| } |
| |
| static class Student { |
| List<Hobby> hobbies; |
| |
| public List<Hobby> getHobbies() { |
| return hobbies; |
| } |
| |
| public void setHobbies(final List<Hobby> hobbies) { |
| this.hobbies = hobbies; |
| } |
| |
| @Override |
| public String toString() { |
| return ToStringBuilder.reflectionToString(this); |
| } |
| } |
| |
| static class Teacher { |
| Hobby[] hobbies; |
| |
| public Hobby[] getHobbies() { |
| return hobbies; |
| } |
| |
| public void setHobbies(final Hobby[] hobbies) { |
| this.hobbies = hobbies; |
| } |
| |
| @Override |
| public String toString() { |
| return ToStringBuilder.reflectionToString(this); |
| } |
| } |
| |
| private final Integer base = Integer.valueOf(5); |
| |
| @BeforeEach |
| public void setUp() { |
| ToStringBuilder.setDefaultStyle(ToStringStyle.JSON_STYLE); |
| } |
| |
| @AfterEach |
| public void tearDown() { |
| ToStringBuilder.setDefaultStyle(ToStringStyle.DEFAULT_STYLE); |
| } |
| |
| @Test |
| void testAppendSuper() { |
| assertEquals( |
| "{}", |
| new ToStringBuilder(base).appendSuper( |
| "Integer@8888[" + System.lineSeparator() + "]") |
| .toString()); |
| assertEquals( |
| "{}", |
| new ToStringBuilder(base).appendSuper( |
| "Integer@8888[" + System.lineSeparator() + " null" |
| + System.lineSeparator() + "]").toString()); |
| assertEquals( |
| "{\"a\":\"hello\"}", |
| new ToStringBuilder(base) |
| .appendSuper( |
| "Integer@8888[" + System.lineSeparator() |
| + "]").append("a", "hello").toString()); |
| assertEquals( |
| "{\"a\":\"hello\"}", |
| new ToStringBuilder(base) |
| .appendSuper( |
| "Integer@8888[" + System.lineSeparator() |
| + " null" + System.lineSeparator() |
| + "]").append("a", "hello").toString()); |
| assertEquals("{\"a\":\"hello\"}", new ToStringBuilder(base) |
| .appendSuper(null).append("a", "hello").toString()); |
| |
| assertEquals("{\"a\":\"hello\",\"b\":\"world\"}", new ToStringBuilder(base) |
| .appendSuper("{\"a\":\"hello\"}").append("b", "world").toString()); |
| } |
| |
| @Test |
| void testArray() { |
| final Person p = new Person(); |
| p.name = "Jane Doe"; |
| p.age = 25; |
| p.smoker = true; |
| |
| assertEquals( |
| "{\"name\":\"Jane Doe\",\"age\":25,\"smoker\":true,\"groups\":['admin', 'manager', 'user']}", |
| new ToStringBuilder(p).append("name", p.name) |
| .append("age", p.age).append("smoker", p.smoker) |
| .append("groups", new Object() { |
| @Override |
| public String toString() { |
| return "['admin', 'manager', 'user']"; |
| } |
| }) |
| .toString()); |
| } |
| |
| @Test |
| void testArrayEnum() { |
| final Teacher teacher = new Teacher(); |
| final Hobby[] hobbies = new Hobby[3]; |
| hobbies[0] = Hobby.BOOK; |
| hobbies[1] = Hobby.SPORT; |
| hobbies[2] = Hobby.MUSIC; |
| |
| teacher.setHobbies(hobbies); |
| |
| assertEquals(teacher.toString(), "{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}"); |
| teacher.setHobbies(new Hobby[0]); |
| assertEquals(teacher.toString(), "{\"hobbies\":[]}"); |
| teacher.setHobbies(null); |
| assertEquals(teacher.toString(), "{\"hobbies\":null}"); |
| } |
| |
| @Test |
| void testBlank() { |
| assertEquals("{}", new ToStringBuilder(base).toString()); |
| } |
| |
| @Test |
| void testBooleanArray() { |
| final boolean[] array = { true, false }; |
| final ToStringBuilder toStringBuilder = new ToStringBuilder(base); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString()); |
| assertEquals("{\"booleanArray\":[true,false]}", toStringBuilder.append("booleanArray", array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| } |
| |
| @Test |
| void testByteArray() { |
| final byte[] array = { 1, 2, -3, 4 }; |
| final ToStringBuilder toStringBuilder = new ToStringBuilder(base); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString()); |
| assertEquals("{\"byteArray\":[1,2,-3,4]}", toStringBuilder.append("byteArray", array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| } |
| |
| @Test |
| void testChar() { |
| assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append('A').toString()); |
| assertEquals("{\"a\":\"A\"}", new ToStringBuilder(base).append("a", 'A').toString()); |
| assertEquals("{\"a\":\"A\",\"b\":\"B\"}", new ToStringBuilder(base).append("a", 'A').append("b", 'B').toString()); |
| } |
| |
| @Test |
| void testCharArray() { |
| final char[] array = { '1', '2', '3', '4' }; |
| final ToStringBuilder toStringBuilder = new ToStringBuilder(base); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString()); |
| assertEquals("{\"charArray\":[\"1\",\"2\",\"3\",\"4\"]}", toStringBuilder.append("charArray", array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| } |
| |
| @Test |
| void testCombineListAndEnum() { |
| final Teacher teacher = new Teacher(); |
| |
| final Hobby[] teacherHobbies = new Hobby[3]; |
| teacherHobbies[0] = Hobby.BOOK; |
| teacherHobbies[1] = Hobby.SPORT; |
| teacherHobbies[2] = Hobby.MUSIC; |
| |
| teacher.setHobbies(teacherHobbies); |
| |
| final Student john = new Student(); |
| john.setHobbies(Arrays.asList(Hobby.BOOK, Hobby.MUSIC)); |
| |
| final Student alice = new Student(); |
| alice.setHobbies(new ArrayList<>()); |
| |
| final Student bob = new Student(); |
| bob.setHobbies(Collections.singletonList(Hobby.BOOK)); |
| |
| final ArrayList<Student> students = new ArrayList<>(); |
| students.add(john); |
| students.add(alice); |
| students.add(bob); |
| |
| final AcademyClass academyClass = new AcademyClass(); |
| academyClass.setStudents(students); |
| academyClass.setTeacher(teacher); |
| |
| assertEquals(academyClass.toString(), "{\"students\":[{\"hobbies\":[\"BOOK\",\"MUSIC\"]},{\"hobbies\":[]},{\"hobbies\":[\"BOOK\"]}],\"teacher\":{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}}"); |
| } |
| |
| @Test |
| void testDate() { |
| final Date now = new Date(); |
| final Date afterNow = new Date(System.currentTimeMillis() + 1); |
| |
| assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append(now).toString()); |
| |
| assertEquals("{\"now\":\"" + now + "\"}", new ToStringBuilder(base).append("now", now).toString()); |
| assertEquals("{\"now\":\"" + now + "\",\"after\":\"" + afterNow + "\"}", |
| new ToStringBuilder(base).append("now", now).append("after", afterNow).toString()); |
| } |
| |
| @Test |
| void testDoubleArray() { |
| final double[] array = { 1, 2, -3, 4 }; |
| final ToStringBuilder toStringBuilder = new ToStringBuilder(base); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString()); |
| assertEquals("{\"doubleArray\":[1.0,2.0,-3.0,4.0]}", toStringBuilder.append("doubleArray", array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| } |
| |
| @Test |
| void testFloatArray() { |
| final float[] array = { 1, 2, -3, 4 }; |
| final ToStringBuilder toStringBuilder = new ToStringBuilder(base); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString()); |
| assertEquals("{\"floatArray\":[1.0,2.0,-3.0,4.0]}", toStringBuilder.append("floatArray", array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| } |
| |
| @Test |
| void testIntArray() { |
| final int[] array = { 1, 2, -3, 4 }; |
| final ToStringBuilder toStringBuilder = new ToStringBuilder(base); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString()); |
| assertEquals("{\"intArray\":[1,2,-3,4]}", toStringBuilder.append("intArray", array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| } |
| |
| @Test |
| void testLANG1395() { |
| assertEquals("{\"name\":\"value\"}", new ToStringBuilder(base).append("name", "value").toString()); |
| assertEquals("{\"name\":\"\"}", new ToStringBuilder(base).append("name", "").toString()); |
| assertEquals("{\"name\":\"\\\"\"}", new ToStringBuilder(base).append("name", '"').toString()); |
| assertEquals("{\"name\":\"\\\\\"}", new ToStringBuilder(base).append("name", '\\').toString()); |
| assertEquals("{\"name\":\"Let's \\\"quote\\\" this\"}", new ToStringBuilder(base).append("name", "Let's \"quote\" this").toString()); |
| } |
| |
| @Test |
| void testLANG1396() { |
| assertEquals("{\"Let's \\\"quote\\\" this\":\"value\"}", new ToStringBuilder(base).append("Let's \"quote\" this", "value").toString()); |
| } |
| |
| @Test |
| void testList() { |
| final Student student = new Student(); |
| final ArrayList<Hobby> objects = new ArrayList<>(); |
| |
| objects.add(Hobby.BOOK); |
| objects.add(Hobby.SPORT); |
| objects.add(Hobby.MUSIC); |
| |
| student.setHobbies(objects); |
| |
| assertEquals(student.toString(), "{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}"); |
| student.setHobbies(new ArrayList<>()); |
| assertEquals(student.toString(), "{\"hobbies\":[]}"); |
| student.setHobbies(null); |
| assertEquals(student.toString(), "{\"hobbies\":null}"); |
| } |
| |
| @Test |
| void testLong() { |
| assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append(3L).toString()); |
| |
| assertEquals("{\"a\":3}", new ToStringBuilder(base).append("a", 3L) |
| .toString()); |
| assertEquals("{\"a\":3,\"b\":4}", |
| new ToStringBuilder(base).append("a", 3L).append("b", 4L) |
| .toString()); |
| } |
| |
| @Test |
| void testLongArray() { |
| final long[] array = { 1, 2, -3, 4 }; |
| final ToStringBuilder toStringBuilder = new ToStringBuilder(base); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString()); |
| assertEquals("{\"longArray\":[1,2,-3,4]}", toStringBuilder.append("longArray", array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| } |
| |
| @Test |
| void testLongArrayArray() { |
| final long[][] array = { { 1, 2 }, null, { 5 } }; |
| final ToStringBuilder toStringBuilder = new ToStringBuilder(base); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((long[][]) null).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| } |
| |
| @Test |
| void testMapSkipNullKey() { |
| final Map<String, Object> map = new LinkedHashMap<>(); |
| map.put("k1", "v1"); |
| map.put(null, "v2"); |
| |
| assertEquals("{\"map\":{\"k1\":\"v1\"}}", |
| new ToStringBuilder(base).append("map", map).toString()); |
| } |
| |
| @Test |
| void testNestedMaps() { |
| final Map<String, Object> innerMap = new LinkedHashMap<>(); |
| innerMap.put("k2.1", "v2.1"); |
| innerMap.put("k2.2", "v2.2"); |
| final Map<String, Object> baseMap = new LinkedHashMap<>(); |
| baseMap.put("k1", "v1"); |
| baseMap.put("k2", innerMap); |
| |
| final InnerMapObject object = new InnerMapObject() { |
| @Override |
| public String toString() { |
| return new ToStringBuilder(this).append("pid", this.pid).append("map", this.map).toString(); |
| } |
| }; |
| object.pid = "dummy-text"; |
| object.map = baseMap; |
| |
| assertEquals("{\"object\":{\"pid\":\"dummy-text\",\"map\":{\"k1\":\"v1\",\"k2\":{\"k2.1\":\"v2.1\",\"k2.2\":\"v2.2\"}}}}", |
| new ToStringBuilder(base).append("object", object).toString()); |
| } |
| |
| @Test |
| void testNestingPerson() { |
| final Person p = new Person() { |
| @Override |
| public String toString() { |
| return new ToStringBuilder(this).append("name", this.name).append("age", this.age).append("smoker", this.smoker).toString(); |
| } |
| }; |
| p.name = "Jane Doe"; |
| p.age = 25; |
| p.smoker = true; |
| |
| final NestingPerson nestP = new NestingPerson(); |
| nestP.pid = "#1@Jane"; |
| nestP.person = p; |
| |
| assertEquals("{\"pid\":\"#1@Jane\",\"person\":{\"name\":\"Jane Doe\",\"age\":25,\"smoker\":true}}", |
| new ToStringBuilder(nestP).append("pid", nestP.pid).append("person", nestP.person).toString()); |
| } |
| |
| @Test |
| void testNull() { |
| assertEquals("null", new ToStringBuilder(null).toString()); |
| } |
| |
| @Test |
| void testObject() { |
| final Integer i3 = Integer.valueOf(3); |
| final Integer i4 = Integer.valueOf(4); |
| assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append((Object) null).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append(i3).toString()); |
| assertEquals("{\"a\":null}", new ToStringBuilder(base).append("a", (Object) null).toString()); |
| assertEquals("{\"a\":3}", new ToStringBuilder(base).append("a", i3).toString()); |
| assertEquals("{\"a\":3,\"b\":4}", new ToStringBuilder(base).append("a", i3).append("b", i4).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append("a", i3, false).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append("a", new ArrayList<>(), false).toString()); |
| assertEquals("{\"a\":[]}", new ToStringBuilder(base).append("a", new ArrayList<>(), true).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append("a", new HashMap<>(), false).toString()); |
| assertEquals("{\"a\":{}}", new ToStringBuilder(base).append("a", new HashMap<>(), true).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append("a", (Object) new String[0], false).toString()); |
| assertEquals("{\"a\":[]}", new ToStringBuilder(base).append("a", (Object) new String[0], true).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> new ToStringBuilder(base).append("a", (Object) new int[] { 1, 2, 3 }, false).toString()); |
| assertEquals("{\"a\":[1,2,3]}", new ToStringBuilder(base).append("a", (Object) new int[] { 1, 2, 3 }, true).toString()); |
| assertThrows(UnsupportedOperationException.class, |
| () -> new ToStringBuilder(base).append("a", (Object) new String[] { "v", "x", "y", "z" }, false).toString()); |
| assertEquals("{\"a\":[\"v\",\"x\",\"y\",\"z\"]}", new ToStringBuilder(base).append("a", (Object) new String[] { "v", "x", "y", "z" }, true).toString()); |
| } |
| |
| @Test |
| void testObjectArray() { |
| final Object[] array = { null, base, new int[] { 3, 6 } }; |
| final ToStringBuilder toStringBuilder = new ToStringBuilder(base); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString()); |
| assertEquals("{\"objectArray\":[null,5,[3,6]]}", toStringBuilder.append("objectArray", array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object[]) null).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| } |
| |
| @Test |
| void testObjectWithInnerMap() { |
| final Map<String, Object> map = new LinkedHashMap<>(); |
| map.put("k1", "value1"); |
| map.put("k2", 2); |
| |
| final InnerMapObject object = new InnerMapObject() { |
| @Override |
| public String toString() { |
| return new ToStringBuilder(this).append("pid", this.pid).append("map", this.map).toString(); |
| } |
| }; |
| object.pid = "dummy-text"; |
| object.map = map; |
| |
| assertEquals("{\"object\":{\"pid\":\"dummy-text\",\"map\":{\"k1\":\"value1\",\"k2\":2}}}", |
| new ToStringBuilder(base).append("object", object).toString()); |
| } |
| |
| @Test |
| void testPerson() { |
| final Person p = new Person(); |
| p.name = "Jane Doe"; |
| p.age = 25; |
| p.smoker = true; |
| |
| assertEquals( |
| "{\"name\":\"Jane Doe\",\"age\":25,\"smoker\":true}", |
| new ToStringBuilder(p).append("name", p.name) |
| .append("age", p.age).append("smoker", p.smoker) |
| .toString()); |
| } |
| |
| @Test |
| void testRootMap() { |
| final Map<String, Object> map = new LinkedHashMap<>(); |
| map.put("k1", "v1"); |
| map.put("k2", 2); |
| |
| assertEquals("{\"map\":{\"k1\":\"v1\",\"k2\":2}}", |
| new ToStringBuilder(base).append("map", map).toString()); |
| } |
| |
| @Test |
| void testShortArray() { |
| final short[] array = { 1, 2, -3, 4 }; |
| final ToStringBuilder toStringBuilder = new ToStringBuilder(base); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append(array).toString()); |
| assertEquals("{\"shortArray\":[1,2,-3,4]}", toStringBuilder.append("shortArray", array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((long[]) null).toString()); |
| assertThrows(UnsupportedOperationException.class, () -> toStringBuilder.append((Object) array).toString()); |
| } |
| } |