英文:
ObjectMapper doesn't fail on trailing characters
问题
我有以下的类:
public class Car {
private String id;
private String name;
public Car() {
}
public Car(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我使用它的方式如下:
String json = "{\"id\":\"1\", \"name\":\"hh\"} {\"id\":\"2\", \"name\":\"ccc\"}";
Car car;
try {
ObjectMapper mapper = new ObjectMapper();
car = mapper.readValue(json, new TypeReference<Car>() {
});
} catch (IOException e) {
car = null;
}
我预期它会失败,但实际上,我得到了输入中的第一个对象,即“第一个”汽车对象。
为什么会发生这种情况呢?
英文:
I'm having the following class:
public class Car{
private String id;
private String name;
public Car() {
}
public Car(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and I use it like this:
String json = "{\"id\":\"1\", \"name\":\"hh\"} {\"id\":\"2\", \"name\":\"ccc\"}";
Car car;
try {
ObjectMapper mapper = new ObjectMapper();
car = mapper.readValue(json, new TypeReference<Car>() {
});
} catch (IOException e) {
car = null;
}
I'm expecting it to fail but instead, I get the first object in the input, the "first" car object.
why is that happening?
答案1
得分: 2
你需要启用 FAIL_ON_TRAILING_TOKENS 功能以在这种情况下抛出异常:
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
或者自版本 2.10
起:
ObjectMapper mapper = JsonMapper.builder()
.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
.build();
来自文档:
> 此功能确定绑定根值后数据绑定的行为。如果启用了该功能,将会多调用一次 JsonParser.nextToken()
来确保没有找到更多的标记
> (如果找到任何标记,将抛出 MismatchedInputException
);如果禁用,将不再进行进一步的检查。该功能也可以称为 READ_FULL_STREAM
,
> 因为它实际上验证输入流只包含所需的用于绑定完整值的数据,不多也不少(除非数据格式支持可能的可忽略的空白或注释)。
>
> 该功能在默认情况下被禁用(因此不会对可能的尾随标记进行检查),这是为了保持向后兼容性。
你可以启用 FAIL_ON_*
系列中的所有功能,以使其尽可能严格。
英文:
You need to enable FAIL_ON_TRAILING_TOKENS feature to throw an exception in this case:
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
or since version 2.10
:
ObjectMapper mapper = JsonMapper.builder()
.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
.build();
From documentation:
> Feature that determines behaviour for data-binding after binding the
> root value. If feature is enabled, one more call to
> JsonParser.nextToken()
is made to ensure that no more tokens are found
> (and if any is found, MismatchedInputException
is thrown); if
> disabled, no further checks are made. Feature could alternatively be
> called READ_FULL_STREAM
, since it effectively verifies that input
> stream contains only as much data as is needed for binding the full
> value, and nothing more (except for possible ignorable white space or
> comments, if supported by data format).
>
> Feature is disabled by default (so that no check is made for possible
> trailing token(s)) for backwards compatibility reasons.
You can enable all features from FAIL_ON_*
family to be as strict as possible.
答案2
得分: 0
替代方案。
注意,您的类型引用不是`Car`,而是`Car`的`List`。
final ObjectMapper mapper = new ObjectMapper();
final TypeReference<List
final String json = "{"id":"1", "name":"hh"} {"id":"2", "name":"ccc"}";
List
try {
cars = mapper.readValue(json, typeReference);
} catch (IOException e) {
e.printStackTrace(); // TODO - 请处理异常
cars = null;
}
System.out.println("Cars: " + cars);
将会打印出:
com.fasterxml.jackson.databind.exc.MismatchedInputException: 无法从START_OBJECT标记反序列化java.util.ArrayList<com.yk.training.backperssure.Car>
的实例
at [Source: (String)"{"id":"1", "name":"hh"} {"id":"2", "name":"ccc"}"; line: 1, column: 1]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1464)
// 更多堆栈跟踪...
Cars: null
英文:
Alternative.
Note, your type reference is not a Car
, but a List
of Car
s.
final ObjectMapper mapper = new ObjectMapper();
final TypeReference<List<Car>> typeReference = new TypeReference<List<Car>>() {};
final String json = "{\"id\":\"1\", \"name\":\"hh\"} {\"id\":\"2\", \"name\":\"ccc\"}";
List<Car> cars = null;
try {
cars = mapper.readValue(json, typeReference);
} catch (IOException e) {
e.printStackTrace(); // TODO - Please, handle it
cars = null;
}
System.out.println("Cars: " + cars);
It will print:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList<com.yk.training.backperssure.Car>` out of START_OBJECT token
at [Source: (String)"{"id":"1", "name":"hh"} {"id":"2", "name":"ccc"}"; line: 1, column: 1]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1464)
// More stack trace.,..\
Cars: null
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论