@Override public ListResource<T> deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException { JsonNode node = parser.getCodec().readTree(parser); // Find the first unrecognised field that is an array Optional<Map.Entry<String, JsonNode>> field = CommonUtil.stream(node.fields()) .filter(f -> !RECOGNISED_KEYS.contains(f.getKey())) .filter(f -> f.getValue().isArray()) // There might be multiple fields that are arrays, so we pick the first one and ignore the others .sorted().findFirst(); if (!field.isPresent()) { throw InvalidFormatException.from(parser, ListResource.class, "Expected a field containing a list"); } String key = field.get().getKey(); JsonNode value = field.get().getValue(); List<T> items = value.traverse().readValueAs(new TypeReference<List<T>>(){}); Link selfLink = node.get("@id").traverse().readValueAs(Link.class); return ListResource.create(selfLink, key, items); }
@ExceptionHandler({HttpMessageNotReadableException.class, InvalidJsonException.class, InvalidFormatException.class}) @ResponseStatus(value = HttpStatus.BAD_REQUEST) public ResponseError handleInputNotReadableException(Exception exception) { final Throwable cause = exception.getCause() == null ? exception : exception.getCause(); if (cause instanceof UnrecognizedPropertyException) { return constructError("error.invalid_json_key", ((UnrecognizedPropertyException) cause).getPropertyName()); } else if (cause instanceof InvalidTypeIdException || (cause instanceof JsonMappingException && cause.getMessage() .contains("missing property 'type'"))) { return constructError("error.invalid_type_with_set_prompt"); } else if (cause instanceof InvalidFormatException) { for (InvalidFormatException.Reference reference : ((InvalidFormatException) cause) .getPath()) { if ("operations".equals(reference.getFieldName())) { return constructError("error.permission.invalid_operation"); } } } return badRequestResponse(); }
private ErrorListDto createParsingError(InvalidFormatException invalidFormatException) { //Get the Name of the Processor String nameOfProcessor = invalidFormatException.getProcessor().getClass().getSimpleName(); //Decide between different input types like excel or json files switch (nameOfProcessor) { //Excel Parsing Error case "TreeTraversingParser": return this.createExcelParsingError(invalidFormatException); //Json Parsing Error case "UTF8StreamJsonParser": return this.createJsonParsingError(invalidFormatException); default: return new ErrorListDto(); } }
private ErrorListDto createJsonParsingError(InvalidFormatException invalidFormatException) { UTF8StreamJsonParser processor = (UTF8StreamJsonParser) invalidFormatException.getProcessor(); //Create Json Parsing Error. Just the first will be returned try { String domainObject = ((Class<?>) invalidFormatException.getPath().get(0).getFrom()) .getSimpleName(); String property = processor.getCurrentName(); if (property == null) { property = invalidFormatException.getPath().get(0).getFieldName(); } String invalidValue = (String)invalidFormatException.getValue(); String messageKey = "global.error.import.json-parsing-error"; return new ErrorListDto(new ErrorDto(domainObject, messageKey,invalidValue, property)); } catch (IOException e) { return new ErrorListDto( new ErrorDto(null, "global.error.import.no-json-mapping", null, null)); } }
public static Error from(JsonMappingException e) { String path = e.getPath().stream().map(x -> x.getFieldName()).collect(Collectors.joining(" -> ")); if (e instanceof InvalidFormatException) { InvalidFormatException ex = (InvalidFormatException) e; return new Error( String.format("Invalid value for %s. Expected value of type %s but got: '%s'", path, ex.getTargetType().getSimpleName(), ex.getValue()), e ); } else if (e instanceof IgnoredPropertyException) { return new Error(String.format("Missing value for %s", path), e); } else if (e instanceof UnrecognizedPropertyException) { return new Error(String.format("Unknown property: %s", path), e); } else { return new Error(String.format("Cannot parse JSON data for property %s", path), e); } }
@Test public void arrayItemsAreNotRecursivelyMerged() throws Exception { ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/yaml/simplePropertiesInArrayItem.yaml", "com.example", config("sourceType", "yaml")); Class<?> genType = resultsClassLoader.loadClass("com.example.SimplePropertiesInArrayItem"); // Different array items use different types for the same property; // we don't support union types, so we have to pick one assertEquals(Integer.class, genType.getMethod("getScalar").getReturnType()); thrown.expect(InvalidFormatException.class); thrown.expectMessage(startsWith("Cannot deserialize value of type `java.lang.Integer` from String \"what\": not a valid Integer value")); OBJECT_MAPPER.readValue(this.getClass().getResourceAsStream("/yaml/simplePropertiesInArrayItem.yaml"), Array.newInstance(genType, 0).getClass()); }
@Test public void arrayItemsAreNotRecursivelyMerged() throws Exception { ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/json/simplePropertiesInArrayItem.json", "com.example", config("sourceType", "json")); Class<?> genType = resultsClassLoader.loadClass("com.example.SimplePropertiesInArrayItem"); // Different array items use different types for the same property; // we don't support union types, so we have to pick one assertEquals(Integer.class, genType.getMethod("getScalar").getReturnType()); thrown.expect(InvalidFormatException.class); thrown.expectMessage(startsWith("Cannot deserialize value of type `java.lang.Integer` from String \"what\": not a valid Integer value")); OBJECT_MAPPER.readValue(this.getClass().getResourceAsStream("/json/simplePropertiesInArrayItem.json"), Array.newInstance(genType, 0).getClass()); }
@Test public void shouldThrowExceptionWhenLoadingConfigFileWithInvalidUserAccountAttributes() throws IOException { String badAttribute = "[ \"FIRST_NAME\", \"FIRST_NAME_VERIFIED\", \"INVALID_ATTRIBUTE\" ]"; InputStream badAttributeStream = new ByteArrayInputStream(badAttribute.getBytes()); ObjectMapper mapper = new ObjectMapper(); exception.expect(InvalidFormatException.class); StringContains matcher = new StringContains("\"INVALID_ATTRIBUTE\": value not one of declared Enum instance names: [MIDDLE_NAME_VERIFIED, MIDDLE_NAME, DATE_OF_BIRTH, CURRENT_ADDRESS_VERIFIED, FIRST_NAME, SURNAME, SURNAME_VERIFIED, FIRST_NAME_VERIFIED, CURRENT_ADDRESS, DATE_OF_BIRTH_VERIFIED, ADDRESS_HISTORY, CYCLE_3]"); exception.expectMessage(matcher); mapper.readValue(badAttributeStream, mapper.getTypeFactory().constructCollectionType(List.class, UserAccountCreationAttribute.class)); }
@Override public Response toResponse(InvalidFormatException ex) { String value = ObjectUtils.ifNotNull(ex.getValue(), Object::toString, "NULL"); return ResultStash.builder() .setStatus(Response.Status.PRECONDITION_FAILED) .addFieldError("Invalid JSON field detected.", "invalid.json.field", MapperUtils.printPropertyPath(ex), value) .buildResponse(); }
@Override public JsonError resolveError(Throwable t, Method method, List<JsonNode> arguments) { JsonError error = null; if(t instanceof RskJsonRpcRequestException) { error = new JsonError(((RskJsonRpcRequestException) t).getCode(), t.getMessage(), null); } else if (t instanceof InvalidFormatException) { error = new JsonError(-32603, "Internal server error, probably due to invalid parameter type", null); } else { logger.error("JsonRPC error when for method " + method + " with arguments " + arguments, t); error = new JsonError(-32603, "Internal server error", null); } return error; }
private ErrorCodeDto getErrorCodeDto(JsonProcessingException e) { if(e instanceof InvalidFormatException) { return new ErrorCodeDto(ErrorCodeDto.VMIDC_VALIDATION_EXCEPTION_ERROR_CODE, Arrays.asList( "Value " + ((InvalidFormatException) e).getValue() + " is invalid" )); } return new ErrorCodeDto(ErrorCodeDto.VMIDC_VALIDATION_EXCEPTION_ERROR_CODE, Arrays.asList( String.format("Parse exception. Invalid request: %s", e) )); }
@Test public void getInvalid() throws Exception { try { client.basics().getInvalid(); Assert.assertTrue(false); } catch (Exception exception) { // expected Assert.assertEquals(InvalidFormatException.class, exception.getCause().getClass()); } }
/** * Build and return a property path of given exception. */ private StringBuilder buildPropertyPath(final List<InvalidFormatException.Reference> path) { final StringBuilder propertyPath = new StringBuilder(); InvalidFormatException.Reference parent = null; for (final InvalidFormatException.Reference reference : path) { buildPropertyPath(propertyPath, reference, parent); parent = reference; } return propertyPath; }
/** * Build and return a property path of given exception. */ private void buildPropertyPath(final StringBuilder propertyPath, final InvalidFormatException.Reference reference, final InvalidFormatException.Reference parent) { if (parent != null) { buildNestedPropertyPath(propertyPath, reference); } if (reference.getFieldName() != null) { propertyPath.append(reference.getFieldName()); } }
/** * Build nested property path. */ private void buildNestedPropertyPath(final StringBuilder propertyPath, final InvalidFormatException.Reference reference) { if (reference.getIndex() > -1) { propertyPath.append('['); propertyPath.append(reference.getIndex()); propertyPath.append(']'); } else { propertyPath.append('.'); } }
/** * Parse the rule name from the Jackson mapping exception message in the given violation. */ private static String parseRule(final InvalidFormatException mappingException) { final String rule = StringUtils.capitalize(mappingException.getTargetType().getSimpleName()); // Manage the primitive type "int" due to Jackson 2.x new features return "Int".equals(rule) ? "Integer" : rule; }
@Test public void testValidationJsonException() { final InvalidFormatException format = new InvalidFormatException(null, "", "", String.class); format.prependPath(null, "property"); format.prependPath("property", "property2"); final ValidationJsonException validationJsonException = new ValidationJsonException(format); Assert.assertFalse(validationJsonException.getErrors().isEmpty()); Assert.assertEquals("{property2.property=[{rule=String}]}", validationJsonException.getErrors().toString()); }
@Test public void testValidationJsonExceptionInteger() { final InvalidFormatException format = new InvalidFormatException(null, "", "", int.class); format.prependPath(null, "property"); format.prependPath("property", "property2"); final ValidationJsonException validationJsonException = new ValidationJsonException(format); Assert.assertFalse(validationJsonException.getErrors().isEmpty()); Assert.assertEquals("{property2.property=[{rule=Integer}]}", validationJsonException.getErrors().toString()); }
@Test public void testValidationJsonExceptionCollection() throws JsonParseException, JsonMappingException, IOException { final ObjectMapperTrim mapper = new ObjectMapperTrim(); try { mapper.readValue("{\"items\":[{\"value\":\"A\"}]}", CollectionBean.class); } catch (final InvalidFormatException e) { final ValidationJsonException validationJsonException = new ValidationJsonException(e); Assert.assertFalse(validationJsonException.getErrors().isEmpty()); Assert.assertEquals("{items[0].value=[{rule=Integer}]}", validationJsonException.getErrors().toString()); } }
@Test public void testValidationJsonExceptionCollectionNotFound() { final CollectionBean collectionBean = new CollectionBean(); final List<ItemBean> items = new ArrayList<>(); items.add(new ItemBean()); items.add(new ItemBean()); collectionBean.setItems(items); final InvalidFormatException format = new InvalidFormatException(null, "", "", int.class); format.prependPath("any", "id"); format.prependPath(collectionBean, "items"); final ValidationJsonException validationJsonException = new ValidationJsonException(format); Assert.assertFalse(validationJsonException.getErrors().isEmpty()); Assert.assertEquals("{items.id=[{rule=Integer}]}", validationJsonException.getErrors().toString()); }
@Test(expected = InvalidFormatException.class) public void validation_ensuresOperationsAreAllValid() throws Throwable { String json = "{ \n" + "\"actor\": \"dan\",\n" + "\"operations\": [\"foo\", \"read\"]\n" + "}"; try { deserializeAndValidate(json, PermissionEntry.class); } catch (RuntimeException e) { throw e.getCause(); } }
/** * Handler for wrapping exceptions which occur when an unparsable json or excel file * is send by the client. */ @ExceptionHandler(HttpMessageNotReadableException.class) @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorListDto processHttpMessageNotReadableException( HttpMessageNotReadableException exception) { InvalidFormatException invalidFormatException = findInvalidFormatException(exception.getCause()); JsonMappingException jsonMappingException = findJsonMappingException(exception.getCause()); if (invalidFormatException != null) { return createParsingError(invalidFormatException); //Default message, if no other root cause was found } else if (jsonMappingException != null) { return createJsonMappingError(jsonMappingException); } else { String errorMessage; if (exception.getRootCause() != null) { errorMessage = exception.getRootCause() .getLocalizedMessage(); } else { errorMessage = exception.getLocalizedMessage(); } return new ErrorListDto(new ErrorDto(null, errorMessage, null, null)); } }
private InvalidFormatException findInvalidFormatException(Throwable cause) { if (cause == null || cause instanceof InvalidFormatException) { return (InvalidFormatException) cause; } else { return findInvalidFormatException(cause.getCause()); } }
private ErrorListDto createExcelParsingError(InvalidFormatException invalidFormatException) { TreeTraversingParser processor = (TreeTraversingParser) invalidFormatException.getProcessor(); //Create Excel Parsing Error. Just the first will be returned String domainObject = ((Class<?>) invalidFormatException.getPath().get(0).getFrom()) .getSimpleName(); String property = processor.getCurrentName(); if (property == null) { property = invalidFormatException.getPath().get(0).getFieldName(); } String invalidValue = (String)invalidFormatException.getValue(); String messageKey = "global.error.import.excel-parsing-error"; return new ErrorListDto(new ErrorDto(domainObject, messageKey,invalidValue, property)); }
@Override public ECKey deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { JsonToken token = p.getCurrentToken(); switch (token) { case VALUE_STRING: try { return DumpedPrivateKey.fromBase58(null, p.getValueAsString()).getKey(); } catch (AddressFormatException e) { throw new InvalidFormatException(p, "Invalid Key", p.getValueAsString(), ECKey.class); } default: return (ECKey) ctxt.handleUnexpectedToken(ECKey.class, p); } }
@Override public Block deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { JsonToken token = p.getCurrentToken(); switch (token) { case VALUE_STRING: try { byte[] payload = HexUtil.hexStringToByteArray(p.getValueAsString()); // convert to hex return context.getParams().getDefaultSerializer().makeBlock(payload); } catch (ProtocolException e) { throw new InvalidFormatException(p, "Invalid Block", p.getValueAsString(), Block.class); } default: return (Block) ctxt.handleUnexpectedToken(Block.class, p); } }
@Override public Address deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { JsonToken token = p.getCurrentToken(); switch (token) { case VALUE_STRING: try { return Address.fromBase58(netParams, p.getValueAsString()); } catch (AddressFormatException e) { throw new InvalidFormatException(p, "Invalid Address", p.getValueAsString(), Address.class); } default: return (Address) ctxt.handleUnexpectedToken(Address.class, p); } }
/** * Helper method for constructing exception to indicate that given JSON * Object field name was not in format to be able to deserialize specified * key type. */ public JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue, String msg) { return InvalidFormatException.from(_parser, "Can not construct Map key of type "+keyClass.getName()+" from String \""+_desc(keyValue)+"\": "+msg, keyValue, keyClass); }
@Override public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { final String pattern = "MM/dd/yyyy"; SimpleDateFormat dateFormat = new SimpleDateFormat(pattern); String dateText = jp.getText(); Date date; try { date = dateFormat.parse(dateText); } catch (ParseException e) { throw new InvalidFormatException("Date \"" + dateText + "\" can not be parsed in with format \"" + pattern + "\"", dateText, Date.class); } return date; }
@Test(expectedExceptions = InvalidFormatException.class) public void testLoadUnsupportedEffect() throws IOException { File file = new File(POLICY_UNSUPPORTED_EFFECT_FILE_PATH); PolicySets.loadFromFile(file); }
@Override public Response toResponse(final InvalidFormatException ex) { // Set the JSR-303 error into JSON format. return toResponse(Status.BAD_REQUEST, new ValidationJsonException(ex)); }
@Test public void testValidationJsonExceptionEmpty() { final InvalidFormatException format = new InvalidFormatException(null, "", "", String.class); final ValidationJsonException validationJsonException = new ValidationJsonException(format); Assert.assertTrue(validationJsonException.getErrors().isEmpty()); }
@Test public void toResponse() { final InvalidFormatException exception = new InvalidFormatException(null, "", "", String.class); check(mock(new InvalidFormatExceptionMapper()).toResponse(exception), 400, "{\"errors\":{}}"); }
@Test(expected = InvalidFormatException.class) public void testDeserializationFailed() throws IOException { Assert.assertEquals(Status.ACCEPTED, mapper.readValue("\"ACCEPTED\"", Status.class)); }
@Test(expected = InvalidFormatException.class) public void testDeserializationFailed2() throws IOException { Assert.assertEquals(Status.ACCEPTED, vanillaMapper.readValue("\"accepted\"", Status.class)); }
public JsonMappingException weirdKeyException(Class<?> paramClass, String paramString1, String paramString2) { return InvalidFormatException.from(this._parser, "Can not construct Map key of type " + paramClass.getName() + " from String \"" + _desc(paramString1) + "\": " + paramString2, paramString1, paramClass); }
public JsonMappingException weirdNumberException(Number paramNumber, Class<?> paramClass, String paramString) { return InvalidFormatException.from(this._parser, "Can not construct instance of " + paramClass.getName() + " from number value (" + _valueDesc() + "): " + paramString, null, paramClass); }
public JsonMappingException weirdStringException(String paramString1, Class<?> paramClass, String paramString2) { return InvalidFormatException.from(this._parser, "Can not construct instance of " + paramClass.getName() + " from String value '" + _valueDesc() + "': " + paramString2, paramString1, paramClass); }
@Override public Enum<?> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { String text = jp.getText(); Enum<?> defaultEnum = null; try { for (Field field : ReflectionCache.getDeclaredFields(handledType())) { if (field.isEnumConstant()) { String value = propertyValueCache.get(field); if (value == null) { JsonProperty property = ReflectionCache.getAnnotation(field, JsonProperty.class); if (property != null) { value = property.value(); propertyValueCache.put(field, value); } } if (text.equals(value)) { return (Enum<?>) field.get(null); } if (ReflectionCache.getAnnotation(field, JsonDefaultEnum.class) != null) { if (defaultEnum == null) { defaultEnum = (Enum<?>) field.get(null); } else { throw new RuntimeException("It can be only one JsonDefaultEnum"); } } } } } catch (Exception ignored) { } try { return (Enum<?>) mapper.readValue("\"" + text + "\"", handledType()); } catch (InvalidFormatException e) { if (defaultEnum != null) { return defaultEnum; } else { throw e; } } }
/** * Helper method for constructing exception to indicate that input JSON * Number was not suitable for deserializing into given target type. */ public JsonMappingException weirdNumberException(Number value, Class<?> instClass, String msg) { return InvalidFormatException.from(_parser, "Can not construct instance of "+instClass.getName()+" from number value ("+_valueDesc()+"): "+msg, null, instClass); }