如何在Jackson JsonMappingException

时间:2019-04-15 00:37:27

标签: java json jackson

我正在使用Jackson来反序列化这种形式的JSON:

{
  "foo" : { "bar" : "baz" } 
}

杰克逊代码可能类似于:

  @JsonCreator
  public class MyProxy {
      @JsonProperty("foo") final FooProxy foo;
  }

  public class FooProxy {
      @JsonProperty("bar") final String bar;
  }

想象一下,此API的使用者创建了这样的无效JSON:

{
  "foo" : { "bar" : 1 }
}

但是,在这种情况下,我收到了MismatchedInputException并且错误看起来像这样:

  

无法构造MyProxy的实例(尽管至少有一个创建者   存在):没有要反序列化的int / Int参数构造函数/工厂方法   从数字值(1)

当我检查MismatchedInputException并致电ex.getPathReference()时,我得到:

  

FooProxy [“ bar”]-> java.lang.Object [0]

我希望能够将残破值的路径返回给用户,而无需任何对底层Java类的引用。

"foo.bar must be an Object."

如何返回带有JSON路径的错误消息,并删除对Java实现的任何引用?

1 个答案:

答案 0 :(得分:1)

应该执行以下操作:

            let animationDuration: Float = 5.0
            let transition = CATransition.init()
            transition.duration = CFTimeInterval(animationDuration)
            transition.type = kCATransitionPush
            transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
            transition.subtype = kCATransitionFromRight
            containerView.layer.add(transition, forKey: nil)

            var rotateIdentity = CATransform3DIdentity
            rotateIdentity.m34 = -1.0/1000
            let rotate = CATransform3DRotate(rotateIdentity, .pi / 6, 0.0, 1.0, 0.0)

            UIView.animate(withDuration: 2.5, animations: {
                containerView.layer.transform = rotate
            }, completion: { _ in
                let rotate2 = CATransform3DRotate(rotateIdentity, .pi / 6, 0.0, 0.0, 0.0)
                UIView.animate(withDuration: 2.5, animations: {
                    containerView.layer.transform = rotate2
                }, completion: nil)
            })

将导致:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;


public class DeserializationErrorTest {

  @Test
  void testDeserializeWrongInput() throws IOException {
    final ObjectMapper mapper = new ObjectMapper();
    try {
      mapper.readValue("{\"foo\" : { \"bar\" : \"not-int\" }}", MyProxy.class);
    } catch (MismatchedInputException e) {
      throw remapMismatchedInputException(e, RuntimeException.class);
    }
  }

  private <T extends Exception> T remapMismatchedInputException(final MismatchedInputException e, Class<T> exClass) {
    try {
      final String fieldName =
          e.getPath().stream().map(JsonMappingException.Reference::getFieldName).collect(Collectors.joining("."));
      return exClass.getConstructor(String.class).newInstance(fieldName + " must be of type " + e.getTargetType().getSimpleName());
    } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException pE) {
      throw new IllegalArgumentException("Cannot instantiate exception class " + exClass.getSimpleName());
    }
  }

  static class MyProxy {
    @JsonProperty("foo") final FooProxy foo;

    @JsonCreator
    public MyProxy(@JsonProperty("foo") final FooProxy pFoo) {foo = pFoo;}
  }

  static class FooProxy {
    @JsonProperty("bar") final Integer bar;

    @JsonCreator
    public FooProxy(@JsonProperty("bar") final Integer pBar) {bar = pBar;}
  }
}