如何使用Jackson JSON验证JSON

48

我正在尝试使用Jackson JSON来获取一个字符串并确定它是否为有效的JSON。 有人可以建议一个可用的代码示例吗?(Java)

我想使用Jackson JSON来判断一个字符串是否是合法的JSON格式。请问有没有可用的Java代码示例可以提供?

1
你如何定义JSON是有效的? - Slavus
3
符合 JSON 语法标准的任何字符串都是有效的 JSON,我们不定义什么是有效的 JSON。 - Vivek
1
我晚了几年,这可能在2012年还没有出现,但你是否考虑过JSON模式? - Stroboskop
7个回答

44

不确定你使用这个的目的是什么,但这应该可以解决:

public boolean isValidJSON(final String json) {
   boolean valid = false;
   try {
      final JsonParser parser = new ObjectMapper().getJsonFactory()
            .createJsonParser(json);
      while (parser.nextToken() != null) {
      }
      valid = true;
   } catch (JsonParseException jpe) {
      jpe.printStackTrace();
   } catch (IOException ioe) {
      ioe.printStackTrace();
   }

   return valid;
}

8
getJsonFactory()方法已过时。 - Arash
5
这里提供了一个简洁优雅的解决方案 感谢 @pdemtry{ ObjectMapper objectMapper = ...; JsonNode jsonNode = objectMapper.readTree(yourJsonString); } catch(JsonProcessingException e){........}注:上述代码需要读取JSON字符串并将其转换成JsonNode对象。 - Abhijeet
1
两种方法均已被弃用:getJsonFactory().createJsonParser(json)。 请使用以下方法:getFactory().createParser(json)。 - kiedysktos
2
我感到困惑,因为在我的信息学研究中我学到了“异常应该用于异常情况;即你不希望发生的事情。”... 验证输入并不是非常特殊的情况。但当然我理解,这是一个有用的解决方案。 - phil
2
嗨。我使用Forify扫描代码。它警告我使用ObjectMapper.read时存在Json注入问题。我已尝试上述解决方案,但无法解决问题。 - Ben Cheng
显示剩余3条评论

25
尽管Perception的答案可能适用于许多需求,但它无法捕获某些问题之一 —— 重复键,考虑以下示例:
String json = "{ \"foo\" : \"bar\", \"foo\" : \"baz\" }";

作为补充,您可以使用以下代码检查重复的键:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
objectMapper.readTree(json);

在出现重复键或其他错误时,它会抛出JsonProcessingException异常。


15

使用Jackson时我使用这个函数:

public static boolean isValidJSON(final String json) throws IOException {
    boolean valid = true;
    try{ 
        objectMapper.readTree(json);
    } catch(JsonProcessingException e){
        valid = false;
    }
    return valid;
}

@mc20 我已经运行了 System.out.println(isValidJSON("{\"foo\":\"bar\"}"));,并且它正常工作,返回了 true。请再试一次。 - madx
4
isValidJSON("{\"foo\":\"bar\"}foo")会失败,因为在有效的 JSON 后面有额外的内容。添加 mapper.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS); 来捕获这种情况。 - mc20
好的,现在我明白你的意思了。 - madx
EOP - 异常导向编程。这不是一个好的模式。 - marciel.deg

13
我建议分开使用 Bean Validation API:即首先将数据绑定到 POJO 中,然后验证 POJO。在我看来,数据格式级别的模式不是非常有用:通常还需要验证更高级别的问题,并且模式语言本身很笨拙,特别是那些使用正在验证的格式(XML Schema 和 JSON Schema 都有这个基本缺陷)。
这样做可以使代码更模块化、可重复使用,并分离关注点(序列化、数据验证)。
但我实际上会更进一步,建议您看看 DropWizard -- 它集成了 Jackson 和 Hibernate 项目的验证 API 实现。

Dropwizard似乎已经搬到了新的家(www.dropwizard.io),现在称自己为“用于开发运维友好、高性能、RESTful Web服务的Java框架”。我还没有深入了解,但它可能仍然集成了Jackson和Validation API。不确定您是否需要其他所有内容。 - Wivani
是的,截至2016年2月,DropWizard仍然集成了Jackson和Validation API。我认为这些不会改变,因为该项目已经非常成熟了。当然,您可以使用其他绑定库(JAX-RS高度可插拔),但作为基线,这两个库可能仍然保持不变。 - StaxMan

3
private boolean isValidJson(String json) {
    try {
        objectMapper.readTree(json);
    } catch (JsonProcessingException e) {
        return false;
    }
    return true;
}

1
改进其他答案
public static boolean isValidJSON(final String json) throws IOException {
    boolean valid = true;
    try{ 
        mapper.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
        mapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
        objectMapper.readTree(json);
    } catch(JsonProcessingException e){
        valid = false;
    }
    return valid;
}

我认为objectMapper.readTree(json);中有一个打字错误,应该是mapper.readTree(json); - LHCHIN

1
另一个选择是在Java 8中使用java.util.Optional。这允许返回一个对象,并在调用代码中使用更加函数式的方法。
这是另一种可能的实现方式:
public Optional<JsonProcessingException> validateJson(final String json) {
    try{ 
        objectMapper.readTree(json);
        return Optional.empty();
    } catch(JsonProcessingException e){
        return Optional.of(e);
    } catch(IOException e) {
        throw new RuntimeException(e);
    }
}

然后,您可以像这样使用此方法:
jsonHelper.validateJson(mappingData.getMetadataJson())
                    .map(e -> String.format("Error: %s at %s", e.getMessage(), e.getLocation().toString()))
                    .orElse("Valid JSON");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接