首页 > 解决方案 > Jackson YAML Parser 删除了特殊字符

问题描述

我在使用带有 YAMLFactory 的 ObjectMapper 来解析 YAML 文件时遇到问题

  1. 我试图解析的 YAML 文件:https ://drive.google.com/open?id=1Q85OmjH-IAIkordikLTsC1oQVTg8ggc8
  2. 使用 readValue 解析文件,如下所示:

    ObjectMapper mapper = new ObjectMapper(new YAMLFactory().enable(Feature.MINIMIZE_QUOTES)// .disable(Feature.WRITE_DOC_START_MARKER)// .disable(YAMLGenerator.Feature.SPLIT_LINES)); TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() {}; HashMap<String, Object> obj = mapper.readValue(responseBuffer.toString(), typeRef);

  3. 通过以下方式将 Obj 转换为 json,然后再次转换为 YAML:

    JsonElement jsonElem = wrapJacksonObject(obj); String cloudTemplateJsonString = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting()// .create()// .toJson(jsonElem); JsonNode jsonNode = mapper.readTree(cloudTemplateJsonString); String yaml = new YAMLMapper().enable(Feature.MINIMIZE_QUOTES)// .disable(Feature.WRITE_DOC_START_MARKER)// .writeValueAsString(jsonNode);

  4. 检查最后一个字符串后,我看到这些特殊字符已更改/删除(它们恰好在第 2 点之后更改):

    一个。' 转移到“ 或已删除 b. !:关于感叹号:它之后的整个字符串直到第一个空格被完全删除

    例子 :

    Version: !Join ['-', [!Ref GatewayVersion, GW]]
    After Parsing  
    Version:
       - '-'
       - - GatewayVersion
       - GW
    

有时单引号也会被删除/转换为双引号

 AllowedPattern: '^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})$'

解析单引号后删除:

 AllowedPattern: ^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})$
  1. 我尝试通过自定义 CharacterEscapes 类的实现来使用转义字符自定义,但它没有帮助

标签: jacksonyaml

解决方案


在 YAML 中,诸如字符串字面量之类的值可以由表示节点元数据(称为节点属性)的标记前置。以 bang 开头的标记!被认为是“节点标签”,以 &开头的标记&是“节点锚点”。

https://yaml.org/spec/1.2/spec.html#id2783797

JSON 没有等效的功能。因为 Jackson 主要是一个 JSON 解析库,其结构化数据节点的内部表示没有元数据字段,因此它的 YAMLFactory 解析器实现简单地丢弃了它们。

查看您的 YAML 文件,我希望文件的预期解析器(aws 的 cloudwatch cli 工具?)会知道如何使用这些 !Join 和 !Ref 节点标签来构建 Version 字段的内部表示。

类似地,围绕文本值的单引号或双引号被认为是标记的一部分(即,使用了解析器)而不是值的一部分。因此解析器会丢弃这些字符(在使用它们作为如何使用值的指南之后)。在将内部表示重新序列化回 YAML 或 JSON 时,可以添加或不添加引号(双引号或单引号)。


推荐阅读