JavaJackson:将复杂的多态对象模型解析:JsonMappingException:意外的token(START_OBSTING),预期的VALUE_STRING

dldeef67  于 2023-11-19  发布在  Java
关注(0)|答案(2)|浏览(135)

我有一个对象树

B扩展A
C延伸B
D延伸B
E延伸C
F扩展A,并且有一个对A的引用
A具有以下注解
第一个月
如果我尝试对扩展为A的对象的JSON数组进行格式化,它会抛出以下错误
org.codehaus.Jackson.map.JsonMappingException:意外的token(START_OBSTAND),expected VALUE_STRING:需要包含类型id的JSON String(用于java.util.Collection的子类型)
json字符串是由set的toString()方法生成的,并且set是A类型的参数,其中A在JSON中序列化,代码如下:

ObjectMapper objectMapper=new ObjectMapper();
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_CONCRETE_AND_ARRAYS);
        String res="";
        try {
            res = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(t);
        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return res;

字符串
将json数组(即上面描述的集合)转换为数组的代码是:

ObjectMapper mapper = new ObjectMapper(); 

        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_CONCRETE_AND_ARRAYS);
        Collection<T> results=null;
        try {
            results =  mapper.readValue(json, TypeFactory.defaultInstance().constructParametricType(Collection.class, clazz ) );
        } catch (JsonParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  
        return results;


它解析的json示例如下:

"[{
  "@class" : "pack1.pack2.MyClass",
  "id" : null,
  "f1" : "",
  "f2" : 0.9933817827,
  "f3" : 6.883261E-4,
  "f4" : 0.001375699,
  "f5" : {
    "@class" : "pack1.pack2.MyClass2",
    "id" : null,
    "f1" : "",
    "f2" : 0.0,
    "f3" : 0.0,
    "f4" : 0.0,
    "f5" : [ "java.util.HashSet", [ 0 ] ],
    "f6" : [ "java.util.HashSet", [ 2 ] ],
    "f7" : [ "java.util.ArrayList", [ "scelta", "brani", "buona" ] ],
    "f8" : [ null, "NOM", null ],
    "f9" : false
  },
  "f10" : [ "java.util.HashMap", {
    "2" : "ADJ"
  } ],
  "f11" : [ "java.util.HashSet", [ 0 ] ],
  "f12" : [ "java.util.HashSet", [ 2 ] ],
  "f13" : [ "java.util.ArrayList", [ "scelta", "brani", "buona" ] ],
  "featureIndicator" : false
}]"


这里的json字符串只包括我的java Set示例中的一些对象

xt0899hw

xt0899hw1#

我相信问题出在默认类型上。JSON的开头并没有像Jackson期望的那样生成默认类型。JSON的开头应该是:

["java.util.HashSet", [{

字符串
末端应该有一个额外的封闭括号}]]
这是因为您使用set中的toString()方法生成JSON。您应该使用ObjectMapper,它配置了默认类型,如下所示:

res = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(yourSet);

gmxoilav

gmxoilav2#

也许它会对某些人有所帮助。在我的例子中,由于Stream.API的toList()方法而发生错误。此方法返回一个不可变的集合,因此,在序列化之后,最终的JSON对象缺少ArrayList类型。Collectors.toList()解决了我的问题
之前

List<B2bItem> itemIdList = branchDto.getOrders()
            .stream()
            .map(order -> order.getItems()
                    .stream()
                    .map(OrderItemDto::getB2bItem)
                    .toList())
            .flatMap(List::stream)
            .toList(); // <---

字符串

List<B2bItem> itemIdList = branchDto.getOrders()
            .stream()
            .map(order -> order.getItems()
                    .stream()
                    .map(OrderItemDto::getB2bItem)
                    .toList())
            .flatMap(List::stream)
            .collect(Collectors.toList()); // <---

相关问题