| /* |
| * 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 |
| * |
| * http://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.johnzon.jsonb; |
| |
| import org.apache.johnzon.mapper.reflection.JohnzonParameterizedType; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| |
| import jakarta.json.Json; |
| import jakarta.json.JsonArray; |
| import jakarta.json.JsonBuilderFactory; |
| import jakarta.json.JsonObject; |
| import jakarta.json.JsonStructure; |
| import jakarta.json.JsonValue; |
| import jakarta.json.bind.Jsonb; |
| import jakarta.json.bind.JsonbBuilder; |
| import jakarta.json.bind.JsonbException; |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.util.ArrayDeque; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Deque; |
| import java.util.EnumMap; |
| import java.util.EnumSet; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Optional; |
| import java.util.OptionalDouble; |
| import java.util.OptionalInt; |
| import java.util.OptionalLong; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| // taken from the examples of the spec |
| // TODO: bunch of asserts |
| //CHECKSTYLE:OFF |
| |
| public class DefaultMappingTest { |
| private static final Jsonb JSONB = JsonbBuilder.create(); |
| |
| @Test |
| @Ignore("should it be supported") |
| public void primitives() throws Exception { |
| fromJsonPrimitives(); |
| toJsonPrimitives(); |
| fromJsonURLURI(); |
| toJsonURLURI(); |
| } |
| |
| @Test |
| public void naming() throws Exception { |
| toJsonDefaultNames(); |
| fromJsonDefaultNames(); |
| } |
| |
| @Test |
| public void collections() { |
| fromJsonCollections(); |
| toJsonCollection(); |
| } |
| |
| @Test |
| public void arrays() { |
| fromJsonArrays(); |
| toJsonArrays(); |
| } |
| |
| @Test |
| public void structures() throws Exception { |
| fromJsonStructures(); |
| toJsonStructures(); |
| } |
| |
| @Test |
| public void pojos() throws Exception { |
| fromJsonPOJOs(); |
| toJsonPOJOs(); |
| } |
| |
| @Test |
| public void inheritance() throws Exception { |
| fromJsonInheritance(); |
| toJsonInheritance(); |
| } |
| |
| @Test |
| public void anonymous() throws Exception { |
| toJsonAnonymousClass(); |
| } |
| |
| @Test |
| public void instantiation() throws Exception { |
| fromJsonInstantiation(); |
| } |
| |
| @Test |
| public void order() throws Exception { |
| toJsonAttributesOrdering(); |
| } |
| |
| @Test |
| public void nulls() throws Exception { |
| toJsonNullValues(); |
| fromJsonNullValues(); |
| } |
| |
| @Test |
| public void modifiers() throws Exception { |
| toJsonModifiers(); |
| fromJsonModifiers(); |
| } |
| |
| @Test |
| public void optionals() throws Exception { |
| toJsonOptional(); |
| fromJsonOptional(); |
| } |
| |
| @Test |
| public void accessors() throws Exception { |
| toJsonAccessors(); |
| fromJsonAccessors(); |
| } |
| |
| @Test |
| public void simpleValues() { |
| assertEquals("\"\\\"strValue\\\"\"", JSONB.toJson("\"strValue\"")); |
| assertEquals("\"true\"", JSONB.toJson("true")); |
| assertEquals("\"false\"", JSONB.toJson("false")); |
| assertEquals("\"null\"", JSONB.toJson("null")); |
| assertEquals("\"strValue\"", JSONB.toJson(Optional.of("strValue"))); |
| assertEquals("null", JSONB.toJson(Optional.ofNullable(null))); |
| assertEquals("null", JSONB.toJson(Optional.empty())); |
| assertEquals("1", JSONB.toJson(OptionalInt.of(1))); |
| assertEquals("null", JSONB.toJson(OptionalInt.empty())); |
| assertEquals("123", JSONB.toJson(OptionalLong.of(123))); |
| assertEquals("null", JSONB.toJson(OptionalLong.empty())); |
| assertEquals("1.2", JSONB.toJson(OptionalDouble.of(1.2))); |
| assertEquals("null", JSONB.toJson(OptionalDouble.empty())); |
| |
| //Optional |
| Optional<String> stringValue = JSONB.fromJson("\"optionalString\"", new JohnzonParameterizedType(Optional.class, String.class)); |
| assertTrue(stringValue.isPresent()); |
| assertEquals("optionalString", stringValue.get()); |
| |
| Optional<String> nullStringValue = JSONB.fromJson("null", new JohnzonParameterizedType(Optional.class, String.class)); |
| assertTrue(!nullStringValue.isPresent()); |
| |
| //OptionalInt |
| OptionalInt optionalInt = JSONB.fromJson("1", OptionalInt.class); |
| assertTrue(optionalInt.isPresent()); |
| assertTrue(optionalInt.getAsInt() == 1); |
| |
| OptionalInt emptyOptionalInt = JSONB.fromJson("null", OptionalInt.class); |
| assertTrue(!emptyOptionalInt.isPresent()); |
| |
| //OptionalLong |
| OptionalLong optionalLong = JSONB.fromJson("123", OptionalLong.class); |
| assertTrue(optionalLong.isPresent()); |
| assertTrue(optionalLong.getAsLong() == 123L); |
| |
| OptionalLong emptyOptionalLong = JSONB.fromJson("null", OptionalLong.class); |
| assertTrue(!emptyOptionalLong.isPresent()); |
| |
| //OptionalDouble |
| OptionalDouble optionalDouble = JSONB.fromJson("1.2", OptionalDouble.class); |
| assertTrue(optionalDouble.isPresent()); |
| assertTrue(optionalDouble.getAsDouble() == 1.2); |
| |
| OptionalDouble emptyOptionalDouble = JSONB.fromJson("null", OptionalDouble.class); |
| assertTrue(!emptyOptionalDouble.isPresent()); |
| |
| final String testText = "test"; |
| assertEquals(testText, JSONB.fromJson(JSONB.toJson(testText), String.class)); |
| } |
| |
| public static void fromJsonPrimitives() { |
| //String |
| String str = JSONB.fromJson("\"some_string\"", String.class); |
| |
| //String escaping |
| String escapedString = JSONB.fromJson("\" \\\" \\\\ \\/ \\b \\f \\n \\r \\t \\u0039\"", String.class); |
| assertEquals(" \" \\ / \b \f \n \r \t 9", escapedString); |
| |
| //Character |
| Character ch = JSONB.fromJson("\"\uFFFF\"", Character.class); |
| |
| //Byte |
| Byte byte1 = JSONB.fromJson("1", Byte.class); |
| |
| //Short |
| Short short1 = JSONB.fromJson("1", Short.class); |
| |
| //Integer |
| Integer int1 = JSONB.fromJson("1", Integer.class); |
| |
| //Long |
| Long long1 = JSONB.fromJson("1", Long.class); |
| |
| //Float |
| Float float1 = JSONB.fromJson("1.2", Float.class); |
| |
| //Double |
| Double double1 = JSONB.fromJson("1.2", Double.class); |
| |
| //BigInteger |
| BigInteger bigInteger = JSONB.fromJson("1", BigInteger.class); |
| |
| //BigDecimal |
| BigDecimal bigDecimal = JSONB.fromJson("1.2", BigDecimal.class); |
| |
| //Number |
| Number number = JSONB.fromJson("1.2", Number.class); |
| |
| //Boolean |
| Boolean trueValue = JSONB.fromJson("true", Boolean.class); |
| |
| //Boolean |
| Boolean falseValue = JSONB.fromJson("false", Boolean.class); |
| |
| //null |
| Object nullValue = JSONB.fromJson("null", Object.class); |
| |
| assertTrue(nullValue == null); |
| } |
| |
| public static void exceptions() { |
| //Exception |
| //fail fast strategy by default |
| |
| //incompatible types |
| try { |
| JSONB.fromJson("not_a_number", Integer.class); |
| assertTrue(false); |
| } catch (JsonbException e) { |
| } |
| |
| //incompatible types |
| try { |
| JSONB.fromJson("[null,1]", int[].class); |
| assertTrue(false); |
| } catch (JsonbException e) { |
| } |
| |
| //bad structure |
| try { |
| JSONB.fromJson("[1,2", int[].class); |
| assertTrue(false); |
| } catch (JsonbException e) { |
| } |
| |
| //overflow - Value out of range |
| try { |
| JSONB.fromJson("" + new Integer(Byte.MAX_VALUE + 1) + "", Byte.class); |
| assertTrue(false); |
| } catch (JsonbException e) { |
| } |
| |
| //underflow - Value out of range |
| try { |
| JSONB.fromJson("" + new Integer(Byte.MIN_VALUE - 1) + "", Byte.class); |
| assertTrue(false); |
| } catch (JsonbException e) { |
| } |
| } |
| |
| public static void toJsonPrimitives() { |
| |
| //String |
| assertEquals("\"some_string\"", JSONB.toJson("some_string")); |
| |
| //escaped String |
| assertEquals("\" \\\\ \\\" / \\b \\f \\n \\r \\t 9\"", JSONB.toJson(" \\ \" / \b \f \n \r \t \u0039")); |
| |
| //Character |
| assertEquals("\"\uFFFF\"", JSONB.toJson('\uFFFF')); |
| |
| //Byte |
| assertEquals("1", JSONB.toJson((byte) 1)); |
| |
| //Short |
| assertEquals("1", JSONB.toJson((short) 1)); |
| |
| //Integer |
| assertEquals("1", JSONB.toJson(1)); |
| |
| //Long |
| assertEquals("5", JSONB.toJson(5L)); |
| |
| //Float |
| assertEquals("1.2", JSONB.toJson(1.2f)); |
| |
| //Double |
| assertEquals("1.2", JSONB.toJson(1.2)); |
| |
| //BigInteger |
| assertEquals("1", JSONB.toJson(new BigInteger("1"))); |
| |
| //BigDecimal |
| assertEquals("1.2", JSONB.toJson(new BigDecimal("1.2"))); |
| |
| //Number |
| assertEquals("1.2", JSONB.toJson((java.lang.Number) 1.2)); |
| |
| //Boolean true |
| assertEquals("true", JSONB.toJson(true)); |
| |
| //Boolean false |
| assertEquals("false", JSONB.toJson(false)); |
| |
| //null |
| assertEquals("null", JSONB.toJson(null)); |
| } |
| |
| public static void fromJsonStructures() { |
| |
| //Map |
| Map<String, Object> map = (Map<String, Object>) JSONB.fromJson("{\"name\":\"unknown object\"}", Object.class); |
| |
| //mapping for number -> Integer, Long, Double |
| Map<String, Object> mapWithBigDecimal = (Map<String, Object>) JSONB.fromJson("{\"intValue\":5,\"longValue\":17179869184,\"doubleValue\":1.2}", Object.class); |
| assertTrue(mapWithBigDecimal.get("intValue") instanceof BigDecimal); |
| assertTrue(mapWithBigDecimal.get("longValue") instanceof BigDecimal); |
| assertTrue(mapWithBigDecimal.get("doubleValue") instanceof BigDecimal); |
| |
| //Collection |
| /* why collection and not array or sthg else? |
| Collection<Object> collection = (Collection<Object>) JSONB.fromJson("[{\"value\":\"first\"}, {\"value\":\"second\"}]", Object.class); |
| */ |
| |
| //JsonStructure |
| assertNotNull(JSONB.fromJson("{\"name\":\"unknown object\"}", JsonStructure.class)); |
| |
| //JsonObject |
| assertNotNull(JSONB.fromJson("{\"name\":\"unknown object\"}", JsonObject.class)); |
| |
| //JsonArray |
| assertNotNull(JSONB.fromJson("[{\"value\":\"first\"},{\"value\":\"second\"}]", JsonArray.class)); |
| |
| //JsonValue |
| assertNotNull(JSONB.fromJson("1", JsonValue.class)); |
| } |
| |
| public static void toJsonStructures() { |
| |
| JsonBuilderFactory factory = Json.createBuilderFactory(Collections.emptyMap()); |
| JsonObject jsonObject = factory.createObjectBuilder(). |
| add("name", "home"). |
| add("city", "Prague") |
| .build(); |
| |
| //JsonObject |
| assertEquals("{\"name\":\"home\",\"city\":\"Prague\"}", JSONB.toJson(jsonObject)); |
| |
| JsonArray jsonArray = factory.createArrayBuilder().add(jsonObject).add(jsonObject).build(); |
| |
| //JsonArray |
| assertEquals("[{\"name\":\"home\",\"city\":\"Prague\"},{\"name\":\"home\",\"city\":\"Prague\"}]", JSONB.toJson(jsonArray)); |
| |
| //JsonStructure |
| assertEquals("[{\"name\":\"home\",\"city\":\"Prague\"},{\"name\":\"home\",\"city\":\"Prague\"}]", JSONB.toJson((JsonStructure) jsonArray)); |
| |
| //JsonValue |
| assertEquals("true", JSONB.toJson(JsonValue.TRUE)); |
| |
| //Map |
| Map<String, Object> commonMap = new LinkedHashMap<>(); |
| commonMap.put("first", 1); |
| commonMap.put("second", 2); |
| |
| assertEquals("{\"first\":1,\"second\":2}", JSONB.toJson(commonMap)); |
| |
| //Collection |
| Collection<Object> commonList = new ArrayList<>(); |
| commonList.add(1); |
| commonList.add(2); |
| |
| assertEquals("[1,2]", JSONB.toJson(commonList)); |
| } |
| |
| public static void fromJsonCollections() { |
| |
| //support deserialization of java.util.Collection and java.util.Map and its subinterfaces and implementing (sub)classes |
| |
| //Collection, Map |
| |
| //Set, HashSet, NavigableSet, SortedSet, TreeSet, LinkedHashSet, TreeHashSet |
| |
| //HashMap, NavigableMap, SortedMap, TreeMap, LinkedHashMap, TreeHashMap |
| |
| //List, ArrayList, LinkedList |
| |
| //Deque, ArrayDeque, Queue, PriorityQueue |
| |
| Collection<Object> collection = JSONB.fromJson("[\"first\",\"second\"]", Collection.class); |
| |
| Map<String, Object> map = JSONB.fromJson("{\"first\":\"second\"}", Map.class); |
| |
| //concrete implementation of Map |
| HashMap<String, Object> hashMap = JSONB.fromJson("{\"first\":\"second\"}", HashMap.class); |
| |
| //concrete implementation of Collection |
| ArrayList<Object> arrayList = JSONB.fromJson("[\"first\",\"second\"]", ArrayList.class); |
| |
| //deque |
| Deque<String> dequeList = JSONB.fromJson("[\"first\",\"second\"]", Deque.class); |
| assertEquals(2, dequeList.size()); |
| assertEquals("first", dequeList.getFirst()); |
| assertEquals("second", dequeList.getLast()); |
| |
| //JSON Binding supports default deserialization of the following interfaces |
| //syntax: interface -> default implementation |
| |
| //Collection -> ArrayList |
| //Set -> HashSet |
| //NavigableSet -> TreeSet |
| //SortedSet -> TreeSet |
| //Map -> HashMap |
| //SortedMap -> TreeMap |
| //NavigableMap -> TreeMap |
| //Deque -> ArrayDeque |
| //Queue -> ArrayDeque |
| |
| //any implementation of Collection and Map with public default constructor is deserializable |
| |
| } |
| |
| public static void toJsonCollection() { |
| Collection<Integer> collection = Arrays.asList(1, 2, 3); |
| |
| assertEquals("[1,2,3]", JSONB.toJson(collection)); |
| |
| Map<String, Integer> map = new LinkedHashMap<>(); |
| map.put("1", 1); |
| map.put("2", 2); |
| map.put("3", 3); |
| |
| assertEquals("{\"1\":1,\"2\":2,\"3\":3}", JSONB.toJson(map)); |
| |
| //any implementation of Collection and Map is serializable |
| |
| //deque |
| Deque<String> deque = new ArrayDeque<>(); |
| deque.add("first"); |
| deque.add("second"); |
| |
| assertEquals("[\"first\",\"second\"]", JSONB.toJson(deque)); |
| } |
| |
| public static void fromJsonArrays() { |
| |
| //support of arrays of types that JSON Binding is able to deserialize |
| //Byte[], Short[], Integer[] Long[], Float[], Double[], BigInteger[], BigDecimal[], Number[] |
| //Object[], JsonArray[], JsonObject[], JsonStructure[] |
| //String[], Character[] |
| //byte[], short[], int[], long[], float[], double[], char[], boolean[] |
| //java.net.URL[], java.net.URI[] |
| //Map[], Collection[], other collections ... |
| //enum, EnumSet, EnumMap |
| //support of multidimensional arrays |
| |
| |
| //Several examples |
| |
| //Byte arrays |
| Byte[] byteArray = JSONB.fromJson("[1,2]", Byte[].class); |
| |
| //Integer array |
| Integer[] integerArray = JSONB.fromJson("[1,2]", Integer[].class); |
| |
| //int array |
| int[] intArray = JSONB.fromJson("[1,2]", int[].class); |
| |
| //String arrays |
| String[] stringArray = JSONB.fromJson("[\"first\",\"second\"]", String[].class); |
| |
| //multidimensional arrays |
| String[][] stringMultiArray = JSONB.fromJson("[[\"first\", \"second\"], [\"third\" , \"fourth\"]]", String[][].class); |
| |
| //default mapping should handle multidimensional arrays of types supported by default mapping, e.g. Map |
| Map<String, Object>[][] mapMultiArray = JSONB.fromJson("[[{\"1\":2}, {\"3\":4}],[{\"5\":6},{\"7\":8}]]", Map[][].class); |
| } |
| |
| public static void toJsonArrays() { |
| |
| //support of arrays of types that JSON Binding is able to serialize |
| //Byte[], Short[], Integer[] Long[], Float[], Double[], BigInteger[], BigDecimal[], Number[] |
| //Object[], JsonArray[], JsonObject[], JsonStructure[] |
| //String[], Character[] |
| //byte[], short[], int[], long[], float[], double[], char[], boolean[] |
| //java.net.URL[], java.net.URI[] |
| //Map[], Collection[], other collections ... |
| //enum, EnumSet, EnumMap |
| //support of multidimensional arrays |
| |
| |
| //Several examples |
| |
| Byte[] byteArray = {1, 2, 3}; |
| |
| assertEquals("[1,2,3]", JSONB.toJson(byteArray)); |
| |
| byte[] rbyteArray = {1, 2, 3}; |
| |
| assertEquals("[1,2,3]", JSONB.toJson(rbyteArray)); |
| |
| Integer[] integerArray = {1, 2, 3}; |
| |
| assertEquals("[1,2,3]", JSONB.toJson(integerArray)); |
| |
| int[] intArray = {1, 2, 3}; |
| |
| assertEquals("[1,2,3]", JSONB.toJson(intArray)); |
| |
| String[] stringArray = {"first", "second", "third"}; |
| |
| assertEquals("[\"first\",\"second\",\"third\"]", JSONB.toJson(stringArray)); |
| |
| String[][] stringMultiArray = {{"first", "second"}, {"third", "fourth"}}; |
| |
| assertEquals("[[\"first\",\"second\"],[\"third\",\"fourth\"]]", JSONB.toJson(stringMultiArray)); |
| |
| Map<String, Object>[][] mapMultiArray = new LinkedHashMap[2][2]; |
| |
| mapMultiArray[0][0] = new LinkedHashMap<>(1); |
| mapMultiArray[0][0].put("0", 0); |
| mapMultiArray[0][1] = new LinkedHashMap<>(1); |
| mapMultiArray[0][1].put("0", 1); |
| mapMultiArray[1][0] = new LinkedHashMap<>(1); |
| mapMultiArray[1][0].put("1", 0); |
| mapMultiArray[1][1] = new LinkedHashMap<>(1); |
| mapMultiArray[1][1].put("1", 1); |
| |
| assertEquals("[[{\"0\":0},{\"0\":1}],[{\"1\":0},{\"1\":1}]]", JSONB.toJson(mapMultiArray)); |
| } |
| |
| public EnumSet<Language> languageEnumSet = EnumSet.of(Language.Czech); |
| public EnumMap<Language, String> languageEnumMap = new EnumMap<>(Language.class); |
| |
| public static void fromJsonEnums() throws Exception { |
| |
| EnumSet<Language> languageEnumSet = JSONB.fromJson("[\"Slovak\", \"English\"]", DefaultMappingTest.class.getField("languageEnumSet").getGenericType()); |
| |
| EnumMap<Language, String> languageEnumMap = JSONB.fromJson("[\"Slovak\" : \"sk\", \"Czech\" : \"cz\"]", DefaultMappingTest.class.getField("languageEnumMap").getGenericType()); |
| } |
| |
| public static void toJsonEnums() { |
| |
| Language language = Language.Slovak; |
| |
| assertEquals("\"Slovak\"", JSONB.toJson(language)); |
| |
| EnumSet<Language> languageEnumSet = EnumSet.of(Language.Czech, Language.Slovak); |
| |
| assertEquals("\"Czech\",\"Slovak\"", JSONB.toJson(languageEnumSet)); |
| |
| EnumMap<Language, String> languageEnumMap = new EnumMap<>(Language.class); |
| languageEnumMap.put(Language.Czech, "cz"); |
| languageEnumMap.put(Language.English, "en"); |
| |
| assertEquals("{\"Czech\":\"cz\",\"English\":\"en\"}", languageEnumMap); |
| } |
| |
| private enum Language { |
| English, Slovak, Czech |
| } |
| |
| public static void fromJsonPOJOs() { |
| |
| POJO pojo = JSONB.fromJson("{\"id\":1, \"name\":\"pojoName\"}", POJO.class); |
| |
| POJO nullPOJO = JSONB.fromJson("{\"id\":1, \"name\":null}", POJO.class); |
| assertTrue(null == nullPOJO.name); |
| |
| //just public nested class |
| try { |
| POJOWithNestedClass pojoWithNestedClass = JSONB.fromJson("{\"id\":1, \"name\":\"pojo_name\", \"nestedClass\" : {\"nestedId\":2, \"nestedName\" : \"nestedPojoName\"}}", POJOWithNestedClass.class); |
| fail(); |
| } catch (final JsonbException e) { |
| // ok |
| } |
| |
| //just public nested class |
| try { |
| POJOWithNestedClass.NestedClass nestedClass = JSONB.fromJson("{\"nestedId\":2, \"nestedName\" : \"nestedPojoName\"}", POJOWithNestedClass.NestedClass.class); |
| fail(); |
| } catch (final JsonbException e) { |
| // ok |
| } |
| |
| POJOWithStaticNestedClass pojoWithStaticNestedClass = JSONB.fromJson("{\"id\":1, \"name\":\"pojoName\"}", POJOWithStaticNestedClass.class); |
| |
| POJOWithStaticNestedClass.StaticNestedClass staticNestedClass = JSONB.fromJson("{\"nestedId\":2, \"nestedName\" : \"nestedPojoName\"}", POJOWithStaticNestedClass.StaticNestedClass.class); |
| |
| POJOWithMixedFieldAccess pojoWithMixedFieldAccess = |
| JSONB.fromJson("{\"id\":5, \"name\":\"new_name\", \"active\":true}"/*, \"valid\":true}"*/, POJOWithMixedFieldAccess.class); |
| |
| assertTrue(pojoWithMixedFieldAccess.id.intValue() == 10); |
| assertTrue(pojoWithMixedFieldAccess.name.equals("new_name")); |
| assertTrue(pojoWithMixedFieldAccess.active); |
| assertNull(pojoWithMixedFieldAccess.valid); |
| |
| //composite class |
| CompositePOJO compositePOJO = JSONB.fromJson( |
| "{\"compositeId\":\"13\"," + |
| "\"stringArray\":[\"first\",\"second\"],\"stringList\":[\"one\",\"two\"]}", CompositePOJO.class); |
| } |
| |
| public static void toJsonPOJOs() { |
| |
| POJO pojo = new POJO(); |
| pojo.setId(1); |
| pojo.setName("pojoName"); |
| |
| assertEquals("{\"id\":1,\"name\":\"pojoName\"}", JSONB.toJson(pojo)); |
| |
| //pojo with nested class |
| POJOWithNestedClass pojoWithNestedClass = new POJOWithNestedClass(); |
| pojoWithNestedClass.setName("pojoName"); |
| pojoWithNestedClass.setId(1); |
| |
| POJOWithNestedClass.NestedClass nestedClass = pojoWithNestedClass.new NestedClass(); |
| nestedClass.setNestedId(2); |
| nestedClass.setNestedName("nestedPojoName"); |
| |
| pojoWithNestedClass.setNestedClass(nestedClass); |
| |
| assertEquals("{\"id\":1,\"name\":\"pojoName\",\"nestedClass\":{\"nestedId\":2,\"nestedName\":\"nestedPojoName\"}}", JSONB.toJson(pojoWithNestedClass)); |
| |
| //nested class |
| assertEquals("{\"nestedId\":2,\"nestedName\":\"nestedPojoName\"}", JSONB.toJson(nestedClass)); |
| |
| //pojo with static nested class |
| POJOWithStaticNestedClass pojoWithStaticNestedClass = new POJOWithStaticNestedClass(); |
| pojoWithStaticNestedClass.setId(1); |
| pojoWithStaticNestedClass.setName("pojoName"); |
| |
| assertEquals("{\"id\":1,\"name\":\"pojoName\"}", JSONB.toJson(pojoWithStaticNestedClass)); |
| |
| //static nested class |
| POJOWithStaticNestedClass.StaticNestedClass staticNestedClass = new POJOWithStaticNestedClass.StaticNestedClass(); |
| staticNestedClass.setNestedId(2); |
| staticNestedClass.setNestedName("nestedPojoName"); |
| |
| assertEquals("{\"nestedId\":2,\"nestedName\":\"nestedPojoName\"}", JSONB.toJson(staticNestedClass)); |
| |
| POJOWithMixedFieldAccess pojoWithMixedFieldAccess = new POJOWithMixedFieldAccess(); |
| |
| assertEquals("{\"active\":true,\"id\":2,\"name\":\"pojoName\",\"valid\":false}", JSONB.toJson(pojoWithMixedFieldAccess)); |
| |
| //composite class |
| CompositePOJO compositePOJO = new CompositePOJO(); |
| compositePOJO.setCompositeId(13); |
| compositePOJO.setStringArray(new String[]{"first", "second"}); |
| compositePOJO.setStringList(Arrays.asList("one", "two")); |
| POJO innerPOJO = new POJO(); |
| innerPOJO.setId(4); |
| innerPOJO.setName("innerPOJO"); |
| compositePOJO.setInner(innerPOJO); |
| |
| assertEquals( |
| "{\"compositeId\":13,\"inner\":{\"id\":4,\"name\":\"innerPOJO\"}," + |
| "\"stringArray\":[\"first\",\"second\"],\"stringList\":[\"one\",\"two\"]}", |
| JSONB.toJson(compositePOJO)); |
| |
| } |
| |
| static class CompositePOJO { |
| private Integer compositeId; |
| private POJO inner; |
| private List<String> stringList; |
| private String[] stringArray; |
| |
| public CompositePOJO() { |
| } |
| |
| public Integer getCompositeId() { |
| return compositeId; |
| } |
| |
| public void setCompositeId(Integer compositeId) { |
| this.compositeId = compositeId; |
| } |
| |
| public POJO getInner() { |
| return inner; |
| } |
| |
| public void setInner(POJO inner) { |
| this.inner = inner; |
| } |
| |
| public List<String> getStringList() { |
| return stringList; |
| } |
| |
| public void setStringList(List<String> stringList) { |
| this.stringList = stringList; |
| } |
| |
| public String[] getStringArray() { |
| return stringArray; |
| } |
| |
| public void setStringArray(String[] stringArray) { |
| this.stringArray = stringArray; |
| } |
| } |
| |
| public static class POJO { |
| private Integer id; |
| private String name; |
| |
| public POJO() { |
| } |
| |
| public Integer getId() { |
| return id; |
| } |
| |
| public void setId(Integer id) { |
| this.id = id; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| //other supported attributes |
| } |
| |
| public static class POJOWithNestedClass { |
| private Integer id; |
| private String name; |
| private NestedClass nestedClass; |
| |
| public POJOWithNestedClass() { |
| } |
| |
| public Integer getId() { |
| return id; |
| } |
| |
| public void setId(Integer id) { |
| this.id = id; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public NestedClass getNestedClass() { |
| return nestedClass; |
| } |
| |
| public void setNestedClass(NestedClass nestedClass) { |
| this.nestedClass = nestedClass; |
| } |
| |
| //other supported attributes |
| |
| public class NestedClass { |
| private Integer nestedId; |
| private String nestedName; |
| |
| public NestedClass() { |
| } |
| |
| public Integer getNestedId() { |
| return nestedId; |
| } |
| |
| public void setNestedId(Integer nestedId) { |
| this.nestedId = nestedId; |
| } |
| |
| public String getNestedName() { |
| return nestedName; |
| } |
| |
| public void setNestedName(String nestedName) { |
| this.nestedName = nestedName; |
| } |
| } |
| } |
| |
| public static class POJOWithStaticNestedClass { |
| private Integer id; |
| private String name; |
| |
| public POJOWithStaticNestedClass() { |
| } |
| |
| public Integer getId() { |
| return id; |
| } |
| |
| public void setId(Integer id) { |
| this.id = id; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| //other supported attributes |
| |
| public static class StaticNestedClass { |
| private Integer nestedId; |
| private String nestedName; |
| |
| public StaticNestedClass() { |
| } |
| |
| public Integer getNestedId() { |
| return nestedId; |
| } |
| |
| public void setNestedId(Integer nestedId) { |
| this.nestedId = nestedId; |
| } |
| |
| public String getNestedName() { |
| return nestedName; |
| } |
| |
| public void setNestedName(String nestedName) { |
| this.nestedName = nestedName; |
| } |
| } |
| } |
| |
| public static class POJOWithMixedFieldAccess { |
| public Integer id = 1; |
| public String name = "pojoName"; |
| public Boolean active = false; |
| public Boolean valid = null; |
| |
| public Integer getId() { |
| return 2; |
| } |
| |
| public void setId(Integer id) { |
| this.id = id * 2; |
| } |
| |
| public Boolean getActive() { |
| return true; |
| } |
| |
| public void setActive(Boolean active) { |
| this.active = active; |
| } |
| |
| public Boolean isValid() { |
| return false; |
| } |
| |
| public void setValid(Boolean valid) { |
| this.valid = valid; |
| } |
| } |
| |
| private static void fromJsonInheritance() { |
| //we need public constructor |
| Dog animal = JSONB.fromJson("{\"age\":5, \"name\":\"Rex\"}", Dog.class); |
| } |
| |
| public static void toJsonInheritance() { |
| |
| Dog dog = new Dog(); |
| dog.setAge(5); |
| dog.setName("Rex"); |
| |
| assertEquals("{\"age\":5,\"name\":\"Rex\"}", JSONB.toJson(dog), JSONB.toJson(dog)); |
| } |
| |
| public static class Animal { |
| int age; |
| |
| public Animal() { |
| } |
| |
| public int getAge() { |
| return age; |
| } |
| |
| public void setAge(int age) { |
| this.age = age; |
| } |
| } |
| |
| public static class Dog extends Animal { |
| private String name; |
| |
| public Dog() { |
| super(); |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| } |
| |
| public static void toJsonAnonymousClass() { |
| assertEquals("{\"id\":1,\"name\":\"pojoName\"}", JSONB.toJson(new POJO() { |
| @Override |
| public Integer getId() { |
| return 1; |
| } |
| |
| @Override |
| public String getName() { |
| return "pojoName"; |
| } |
| })); |
| |
| } |
| |
| public static void fromJsonURLURI() { |
| java.net.URL url = JSONB.fromJson("\"https://www.jcp.org/en/jsr/detail?id=367#3\"", java.net.URL.class); |
| |
| java.net.URI uri = JSONB.fromJson("\"mailto:users@JSONB-spec.java.net\"", java.net.URI.class); |
| } |
| |
| public static void toJsonURLURI() throws Exception { |
| |
| java.net.URL url = new java.net.URL("https://www.jcp.org/en/jsr/detail?id=367#3"); |
| |
| assertEquals("\"https://www.jcp.org/en/jsr/detail?id=367#3\"", JSONB.toJson(url)); |
| |
| java.net.URI uri = new java.net.URI("mailto:users@JSONB-spec.java.net"); |
| |
| assertEquals("\"mailto:users@JSONB-spec.java.net\"", JSONB.toJson(uri)); |
| } |
| |
| static class POJOWithoutDefaultArgConstructor { |
| public String id; |
| |
| public POJOWithoutDefaultArgConstructor(String id) { |
| this.id = id; |
| } |
| } |
| |
| static class POJOWithPrivateConstructor { |
| public String id; |
| |
| private POJOWithPrivateConstructor() { |
| } |
| } |
| |
| public static void fromJsonInstantiation() { |
| |
| //public or protected constructor must be present |
| |
| try { |
| POJOWithoutDefaultArgConstructor pojo = JSONB.fromJson("{\"id\":\"1\"}", POJOWithoutDefaultArgConstructor.class); |
| fail(); |
| } catch (JsonbException e) { |
| } |
| |
| /* TBD: protected or private is the same |
| try { |
| JSONB.fromJson("{\"id\":\"1\"}", POJOWithPrivateConstructor.class); |
| fail(); |
| } catch (JsonbException e) { |
| } |
| */ |
| } |
| |
| public static void toJsonDefaultNames() { |
| DefaultTestNames defaultTestNames = new DefaultTestNames(); |
| String result = JSONB.toJson(defaultTestNames); |
| assertEquals("{\"A\":\"A\",\"ABC\":\"ABC\",\"A_Bc\":\"A_Bc\",\"DdB_ee\":\"DdB_ee\",\"_12ac\":\"_12ac\"," + |
| "\"_23_45_a\":\"_23_45_a\",\"_AB\":\"_AB\",\"_ABc\":\"_ABc\",\"_Ab\":\"_Ab\"," + |
| "\"a\":\"a\",\"a_bC\":\"a_bC\",\"abc\":\"abc\",\"okNotOk\":\"okNotOk\"," + |
| "\"okNot_Ok\":\"okNot_Ok\",\"okNot_ok\":\"okNot_ok\"}", result); |
| } |
| |
| public static void fromJsonDefaultNames() { |
| DefaultNames defaultNames = JSONB.fromJson("{\"defaultName\":\"newName\"}", DefaultNames.class); |
| assertEquals("newName", defaultNames.defaultName); |
| assertNull(JSONB.fromJson("{\"defaultNAME\":\"newName\"}", DefaultNames.class).defaultName); |
| } |
| |
| static class DefaultNames { |
| public String defaultName; |
| |
| public DefaultNames() { |
| } |
| } |
| |
| static class DefaultTestNames { |
| public String a = "a"; |
| public String A = "A"; |
| public String ABC = "ABC"; |
| public String abc = "abc"; |
| public String a_bC = "a_bC"; |
| public String A_Bc = "A_Bc"; |
| public String _12ac = "_12ac"; |
| public String _Ab = "_Ab"; |
| public String _AB = "_AB"; |
| public String _ABc = "_ABc"; |
| public String okNotOk = "okNotOk"; |
| public String okNot_Ok = "okNot_Ok"; |
| public String okNot_ok = "okNot_ok"; |
| public String DdB_ee = "DdB_ee"; |
| public String _23_45_a = "_23_45_a"; |
| } |
| |
| public static void toJsonAttributesOrdering() { |
| //lexicographical order |
| AttributesOrderingClass attributesOrderingClass = new AttributesOrderingClass(); |
| attributesOrderingClass.aField = "text"; |
| attributesOrderingClass.cField = "text"; |
| attributesOrderingClass.bField = "text"; |
| |
| assertEquals("{\"aField\":\"text\",\"bField\":\"text\",\"cField\":\"text\"}", JSONB.toJson(attributesOrderingClass)); |
| |
| AttributesOrderingWithInheritance attributesOrderingWithInheritance = new AttributesOrderingWithInheritance(); |
| attributesOrderingWithInheritance.aField = "aField"; |
| attributesOrderingWithInheritance.cField = "cField"; |
| attributesOrderingWithInheritance.bField = "bField"; |
| attributesOrderingWithInheritance.aa = "aa"; |
| attributesOrderingWithInheritance.cc = "cc"; |
| attributesOrderingWithInheritance.bb = "bb"; |
| |
| assertEquals("{\"aField\":\"aField\",\"bField\":\"bField\",\"cField\":\"cField\",\"aa\":\"aa\",\"bb\":\"bb\",\"cc\":\"cc\"}", |
| JSONB.toJson(attributesOrderingWithInheritance)); |
| |
| // important, see OrderTest#deserializationRespectsOrderToo |
| AttributesOrderingWithCounterClass attributesOrderingWithCounterClass = JSONB.fromJson("{\"second\":\"a\",\"third\":\"b\",\"first\":\"c\"}", AttributesOrderingWithCounterClass.class); |
| assertEquals("a0", attributesOrderingWithCounterClass.second); |
| assertEquals("b1", attributesOrderingWithCounterClass.third); |
| assertEquals("c2", attributesOrderingWithCounterClass.first); |
| } |
| |
| public static void toJsonNullValues() { |
| //array |
| List<String> stringList = new ArrayList<>(); |
| stringList.add("value1"); |
| stringList.add(null); |
| stringList.add("value3"); |
| |
| assertEquals("[\"value1\",null,\"value3\"]", JSONB.toJson(stringList)); |
| |
| //java object |
| POJO pojo = new POJO(); |
| pojo.id = 1; |
| pojo.name = null; |
| |
| assertEquals("{\"id\":1}", JSONB.toJson(pojo)); |
| } |
| |
| public static void fromJsonNullValues() { |
| //array |
| ArrayList<Object> stringList = JSONB.fromJson("[\"value1\",null,\"value3\"]", ArrayList.class); |
| assertTrue(stringList.size() == 3); |
| Iterator<Object> iterator = stringList.iterator(); |
| assertEquals("value1", iterator.next()); |
| assertTrue(null == iterator.next()); |
| assertEquals("value3", iterator.next()); |
| |
| //java object |
| POJOWithInitialValue pojoWithInitialValue = JSONB.fromJson("{\"name\":\"newName\"}", POJOWithInitialValue.class); |
| assertTrue(pojoWithInitialValue.id.intValue() == 4); |
| assertEquals("newName", pojoWithInitialValue.name); |
| |
| POJOWithInitialValue pojoWithNullValue = JSONB.fromJson("{\"name\":\"newName\",\"id\":null}", POJOWithInitialValue.class); |
| assertTrue(pojoWithNullValue.id == null); |
| assertEquals("newName", pojoWithNullValue.name); |
| } |
| |
| public static void toJsonModifiers() { |
| ModifiersClass modifiersClass = new ModifiersClass(); |
| assertEquals("{\"finalField\":\"finalValue\",\"regularField\":\"regularValue\"}", JSONB.toJson(modifiersClass)); |
| } |
| |
| public static void fromJsonModifiers() { |
| //deserialization of final field is ignored |
| ModifiersClass modifiersClass = JSONB.fromJson("{\"finalField\":\"newFinalValue\",\"regularField\":\"newRegularValue\"}", ModifiersClass.class); |
| assertEquals("finalValue", modifiersClass.finalField); |
| assertEquals("newRegularValue", modifiersClass.regularField); |
| |
| //deserialization of static field is ignored |
| modifiersClass = JSONB.fromJson("{\"staticField\":\"newStaticValue\",\"regularField\":\"newRegularValue\"}", ModifiersClass.class); |
| assertEquals("staticValue", modifiersClass.staticField); |
| assertEquals("newRegularValue", modifiersClass.regularField); |
| |
| //deserialization of transient field is ignored |
| modifiersClass = JSONB.fromJson("{\"transientField\":\"newTransientValue\",\"regularField\":\"newRegularValue\"}", ModifiersClass.class); |
| assertEquals("transientValue", modifiersClass.transientField); |
| assertEquals("newRegularValue", modifiersClass.regularField); |
| |
| //deserialization of unknown field is ignored |
| modifiersClass = JSONB.fromJson("{\"unknownField\":\"newUnknownValue\",\"regularField\":\"newRegularValue\"}", ModifiersClass.class); |
| assertEquals("newRegularValue", modifiersClass.regularField); |
| } |
| |
| public static void toJsonOptional() { |
| final OptionalClass object = new OptionalClass(); |
| object.optionalField = Optional.of("test"); |
| assertEquals("{\"optionalField\":\"test\"}", JSONB.toJson(object)); |
| |
| OptionalClass optionalClass = new OptionalClass(); |
| optionalClass.optionalField = Optional.of("value"); |
| |
| assertEquals("{\"optionalField\":\"value\"}", JSONB.toJson(optionalClass)); |
| |
| OptionalClass nullOptionalField = new OptionalClass(); |
| nullOptionalField.optionalField = null; |
| |
| assertEquals("{}", JSONB.toJson(nullOptionalField)); |
| } |
| |
| public static void fromJsonOptional() { |
| OptionalClass optionalClass = JSONB.fromJson("{\"optionalField\":\"value\"}", OptionalClass.class); |
| assertTrue(optionalClass.optionalField.isPresent()); |
| assertEquals("value", optionalClass.optionalField.get()); |
| |
| OptionalClass emptyOptionalClass = JSONB.fromJson("{}", OptionalClass.class); |
| assertTrue(!emptyOptionalClass.optionalField.isPresent()); |
| |
| OptionalClass nullOptionalClass = JSONB.fromJson("{\"optionalField\":null}", OptionalClass.class); |
| assertFalse(nullOptionalClass.optionalField.isPresent()); |
| } |
| |
| public static void toJsonAccessors() { |
| |
| AccessorsClass accessorsClass = new AccessorsClass(); |
| accessorsClass.setPrivateFieldWithPrivateAccessors(1); |
| accessorsClass.setPrivateFieldWithPublicAccessors(2); |
| accessorsClass.publicField = 3; |
| |
| assertEquals("{\"privateFieldWithPublicAccessors\":2,\"publicField\":3,\"valueWithoutField\":1}", JSONB.toJson(accessorsClass)); |
| } |
| |
| public static void fromJsonAccessors() { |
| AccessorsClass accessorsClass = JSONB.fromJson( |
| "{\"privateFieldWithPrivateAccessors\":5,\"valueWithoutField\":7," + |
| "\"unknownValue\":11,\"transientValue\":9,\"privateFieldWithPublicAccessors\":4,\"publicField\":9," + |
| "\"protectedField\":8,\"defaultField\":13,\"privateField\":17}", |
| AccessorsClass.class); |
| |
| assertEquals(7, accessorsClass.transientValue.intValue()); |
| assertEquals(4, accessorsClass.privateFieldWithPublicAccessors.intValue()); |
| assertEquals(9, accessorsClass.publicField.intValue()); |
| assertNull(accessorsClass.privateFieldWithPrivateAccessors); |
| assertNull(accessorsClass.privateField); |
| assertNull(accessorsClass.defaultField); |
| assertNull(accessorsClass.protectedField); |
| } |
| |
| public static class AccessorsClass { |
| private Integer privateField; |
| |
| protected Integer protectedField; |
| |
| Integer defaultField; |
| |
| public Integer publicField; |
| |
| public transient Integer transientValue; |
| |
| private Integer privateFieldWithPrivateAccessors; |
| |
| private Integer privateFieldWithPublicAccessors; |
| |
| private Integer getPrivateFieldWithPrivateAccessors() { |
| return privateFieldWithPrivateAccessors; |
| } |
| |
| private void setPrivateFieldWithPrivateAccessors(Integer privateFieldWithPrivateAccessors) { |
| this.privateFieldWithPrivateAccessors = privateFieldWithPrivateAccessors; |
| } |
| |
| public Integer getPrivateFieldWithPublicAccessors() { |
| return privateFieldWithPublicAccessors; |
| } |
| |
| public void setPrivateFieldWithPublicAccessors(Integer privateFieldWithPublicAccessors) { |
| this.privateFieldWithPublicAccessors = privateFieldWithPublicAccessors; |
| } |
| |
| public Integer getValueWithoutField() { |
| return 1; |
| } |
| |
| public void setValueWithoutField(Integer valueWithoutField) { |
| transientValue = valueWithoutField; |
| } |
| } |
| |
| public static class OptionalClass { |
| public Optional<String> optionalField = Optional.empty(); |
| |
| public OptionalClass() { |
| } |
| } |
| |
| public static class ModifiersClass { |
| public final String finalField = "finalValue"; |
| public static String staticField = "staticValue"; |
| public transient String transientField = "transientValue"; |
| public String regularField = "regularValue"; |
| |
| public ModifiersClass() { |
| } |
| } |
| |
| public static class POJOWithInitialValue { |
| public Integer id = 4; |
| public String name; |
| |
| public POJOWithInitialValue() { |
| } |
| } |
| |
| public static class AttributesOrderingClass { |
| public String aField; |
| public String cField; |
| public String bField; |
| |
| public AttributesOrderingClass() { |
| } |
| } |
| |
| public static class AttributesOrderingWithInheritance extends AttributesOrderingClass { |
| public String aa; |
| public String cc; |
| public String bb; |
| |
| public AttributesOrderingWithInheritance() { |
| } |
| } |
| |
| public static class AttributesOrderingWithCounterClass { |
| private transient int counter = 0; |
| |
| private String first = "first"; |
| |
| private String second = "second"; |
| |
| private String third = "third"; |
| |
| public AttributesOrderingWithCounterClass() { |
| } |
| |
| public String getFirst() { |
| return first; |
| } |
| |
| public void setFirst(String first) { |
| this.first = first + (counter++); |
| } |
| |
| public String getSecond() { |
| return second; |
| } |
| |
| public void setSecond(String second) { |
| this.second = second + (counter++); |
| } |
| |
| public String getThird() { |
| return third; |
| } |
| |
| public void setThird(String third) { |
| this.third = third + (counter++); |
| } |
| } |
| //CHECKSTYLE:ON |
| } |