1 package com.fasterxml.jackson.databind.convert; 2 3 import com.fasterxml.jackson.core.JsonProcessingException; 4 import com.fasterxml.jackson.databind.*; 5 import com.fasterxml.jackson.databind.cfg.CoercionAction; 6 import com.fasterxml.jackson.databind.cfg.CoercionInputShape; 7 import com.fasterxml.jackson.databind.exc.MismatchedInputException; 8 import com.fasterxml.jackson.databind.type.LogicalType; 9 10 public class CoercePojosTest extends BaseMapTest 11 { 12 static class Bean { 13 public String a; 14 } 15 16 private final ObjectMapper MAPPER = newJsonMapper(); 17 18 private final String JSON_EMPTY = quote(""); 19 private final String JSON_BLANK = quote(" "); 20 21 /* 22 /******************************************************** 23 /* Test methods, from empty String 24 /******************************************************** 25 */ 26 testPOJOFromEmptyStringLegacy()27 public void testPOJOFromEmptyStringLegacy() throws Exception 28 { 29 // first, verify default settings which do not accept empty String: 30 assertFalse(MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)); 31 32 // should be ok to enable dynamically 33 _verifyFromEmptyPass(MAPPER.reader() 34 .with(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT), 35 JSON_EMPTY); 36 37 } 38 testPOJOFromEmptyGlobalConfig()39 public void testPOJOFromEmptyGlobalConfig() throws Exception 40 { 41 _testPOJOFromEmptyGlobalConfig(CoercionInputShape.EmptyString, JSON_EMPTY, null); 42 } 43 testPOJOFromEmptyLogicalTypeConfig()44 public void testPOJOFromEmptyLogicalTypeConfig() throws Exception 45 { 46 _testPOJOFromEmptyLogicalTypeConfig(CoercionInputShape.EmptyString, JSON_EMPTY, null); 47 } 48 testPOJOFromEmptyPhysicalTypeConfig()49 public void testPOJOFromEmptyPhysicalTypeConfig() throws Exception 50 { 51 _testPOJOFromEmptyPhysicalTypeConfig(CoercionInputShape.EmptyString, JSON_EMPTY, null); 52 } 53 54 /* 55 /******************************************************** 56 /* Test methods, from blank String 57 /******************************************************** 58 */ 59 testPOJOFromBlankGlobalConfig()60 public void testPOJOFromBlankGlobalConfig() throws Exception 61 { 62 _testPOJOFromEmptyGlobalConfig(CoercionInputShape.EmptyString, JSON_BLANK, Boolean.TRUE); 63 } 64 testPOJOFromBlankLogicalTypeConfig()65 public void testPOJOFromBlankLogicalTypeConfig() throws Exception 66 { 67 _testPOJOFromEmptyLogicalTypeConfig(CoercionInputShape.EmptyString, JSON_BLANK, Boolean.TRUE); 68 } 69 testPOJOFromBlankPhysicalTypeConfig()70 public void testPOJOFromBlankPhysicalTypeConfig() throws Exception 71 { 72 _testPOJOFromEmptyPhysicalTypeConfig(CoercionInputShape.EmptyString, JSON_BLANK, Boolean.TRUE); 73 } 74 75 /* 76 /******************************************************** 77 /* Second-level helper methods 78 /******************************************************** 79 */ 80 _testPOJOFromEmptyGlobalConfig(final CoercionInputShape shape, final String json, Boolean allowEmpty)81 private void _testPOJOFromEmptyGlobalConfig(final CoercionInputShape shape, final String json, 82 Boolean allowEmpty) 83 throws Exception 84 { 85 ObjectMapper mapper; 86 87 // First, coerce to null 88 mapper = newJsonMapper(); 89 mapper.coercionConfigDefaults().setCoercion(shape, CoercionAction.AsNull) 90 .setAcceptBlankAsEmpty(allowEmpty); 91 assertNull(_verifyFromEmptyPass(mapper, json)); 92 93 // Then coerce as empty 94 mapper = newJsonMapper(); 95 mapper.coercionConfigDefaults().setCoercion(shape, CoercionAction.AsEmpty) 96 .setAcceptBlankAsEmpty(allowEmpty); 97 Bean b = _verifyFromEmptyPass(mapper, json); 98 assertNotNull(b); 99 100 // and finally, "try convert", which aliases to 'null' 101 mapper = newJsonMapper(); 102 mapper.coercionConfigDefaults().setCoercion(shape, CoercionAction.TryConvert) 103 .setAcceptBlankAsEmpty(allowEmpty); 104 assertNull(_verifyFromEmptyPass(mapper, json)); 105 } 106 _testPOJOFromEmptyLogicalTypeConfig(final CoercionInputShape shape, final String json, Boolean allowEmpty)107 private void _testPOJOFromEmptyLogicalTypeConfig(final CoercionInputShape shape, final String json, 108 Boolean allowEmpty) 109 throws Exception 110 { 111 ObjectMapper mapper; 112 113 // First, coerce to null 114 mapper = newJsonMapper(); 115 mapper.coercionConfigFor(LogicalType.POJO).setCoercion(shape, CoercionAction.AsNull) 116 .setAcceptBlankAsEmpty(allowEmpty); 117 assertNull(_verifyFromEmptyPass(mapper, json)); 118 119 // Then coerce as empty 120 mapper = newJsonMapper(); 121 mapper.coercionConfigFor(LogicalType.POJO).setCoercion(shape, CoercionAction.AsEmpty) 122 .setAcceptBlankAsEmpty(allowEmpty); 123 Bean b = _verifyFromEmptyPass(mapper, json); 124 assertNotNull(b); 125 126 // But also make fail again with 2-level settings 127 mapper = newJsonMapper(); 128 mapper.coercionConfigDefaults().setCoercion(shape, CoercionAction.AsNull) 129 .setAcceptBlankAsEmpty(allowEmpty); 130 mapper.coercionConfigFor(LogicalType.POJO).setCoercion(shape, 131 CoercionAction.Fail); 132 _verifyFromEmptyFail(mapper, json); 133 } 134 _testPOJOFromEmptyPhysicalTypeConfig(final CoercionInputShape shape, final String json, Boolean allowEmpty)135 private void _testPOJOFromEmptyPhysicalTypeConfig(final CoercionInputShape shape, final String json, 136 Boolean allowEmpty) 137 throws Exception 138 { 139 ObjectMapper mapper; 140 141 // First, coerce to null 142 mapper = newJsonMapper(); 143 mapper.coercionConfigFor(Bean.class).setCoercion(shape, CoercionAction.AsNull) 144 .setAcceptBlankAsEmpty(allowEmpty); 145 assertNull(_verifyFromEmptyPass(mapper, json)); 146 147 // Then coerce as empty 148 mapper = newJsonMapper(); 149 mapper.coercionConfigFor(Bean.class).setCoercion(shape, CoercionAction.AsEmpty) 150 .setAcceptBlankAsEmpty(allowEmpty); 151 Bean b = _verifyFromEmptyPass(mapper, json); 152 assertNotNull(b); 153 154 // But also make fail again with 2-level settings, with physical having precedence 155 mapper = newJsonMapper(); 156 mapper.coercionConfigFor(LogicalType.POJO).setCoercion(shape, CoercionAction.AsEmpty) 157 .setAcceptBlankAsEmpty(allowEmpty); 158 mapper.coercionConfigFor(Bean.class).setCoercion(shape, CoercionAction.Fail); 159 _verifyFromEmptyFail(mapper, json); 160 } 161 _verifyFromEmptyPass(ObjectMapper m, String json)162 private Bean _verifyFromEmptyPass(ObjectMapper m, String json) throws Exception { 163 return _verifyFromEmptyPass(m.reader(), json); 164 } 165 _verifyFromEmptyPass(ObjectReader r, String json)166 private Bean _verifyFromEmptyPass(ObjectReader r, String json) throws Exception 167 { 168 return r.forType(Bean.class) 169 .readValue(json); 170 } 171 _verifyFromEmptyFail(ObjectMapper m, String json)172 private void _verifyFromEmptyFail(ObjectMapper m, String json) throws Exception 173 { 174 try { 175 m.readValue(json, Bean.class); 176 fail("Should not accept Empty/Blank String for POJO with passed settings"); 177 } catch (MismatchedInputException e) { 178 _verifyFailMessage(e); 179 } 180 } 181 _verifyFailMessage(JsonProcessingException e)182 private void _verifyFailMessage(JsonProcessingException e) 183 { 184 verifyException(e, "Cannot deserialize value of type "); 185 verifyException(e, " from empty String ", " from blank String "); 186 assertValidLocation(e.getLocation()); 187 } 188 } 189