You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含#字符的文档ID触发OJAI解码异常,寻求替代OJAI的迁移方案

移除OJAI库的代码迁移方案及问题解决

原有代码及问题

我有一段使用OJAI库转换并存储JSON文档的旧代码,示例如下:

import org.ojai.Document;

public Object get(String documentId) {
    final Document dto = getDocument(documentId);
      return convert(dto);
}

// 省略其他代码

public Document getDocument(String documentId) {
    return Json.newDocument(documentId);
}

// 省略其他代码

final ObjectMapper objectMapper = new ObjectMapper();

objectMapper.setSerializationInclusion(Include.NON_NULL);
objectMapper.configure(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);
objectMapper.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true);

objectMapper.convertValue(document, CarDto.class);

运行时触发如下错误:

org.ojai.exceptions.DecodingException: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('#' (code 35)): Expected space separating root-level values
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 6]
        at org.ojai.json.impl.JsonStreamDocumentReader.hasMoreTokens(JsonStreamDocumentReader.java:634) ~[ojai-3.0-mapr-1808.jar!/:3.0-mapr-1808]

推测是格式为12345#CAR#RED的文档ID导致报错,以下是完全移除OJAI库的迁移方案:


问题根源

Json.newDocument(documentId)会把传入的字符串当作JSON内容直接解析,但12345#CAR#RED并非合法JSON格式,OJAI底层调用Jackson解析时,因#是JSON根级非法字符触发语法错误。


迁移方案(彻底移除OJAI)

1. 移除OJAI相关依赖与代码

  • 删除所有org.ojai.Document类的导入语句
  • 删除所有依赖OJAI Document对象的方法与逻辑,改用Jackson原生API处理JSON

2. 重构文档获取逻辑

根据原代码的实际业务场景,分两种情况调整:

场景1:从存储读取JSON内容

如果原getDocument是根据ID从存储(数据库/文件等)读取JSON,直接返回JSON字符串或字节流:

// 替换原有getDocument方法
public String getDocumentJson(String documentId) {
    // 替换为实际的存储读取逻辑,比如从数据库查询JSON字符串
    return fetchJsonFromStorage(documentId);
}

public Object get(String documentId) {
    String jsonStr = getDocumentJson(documentId);
    return convert(jsonStr);
}

// 转换方法直接用Jackson解析JSON字符串
private CarDto convert(String jsonStr) throws IOException {
    final ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setSerializationInclusion(Include.NON_NULL);
    objectMapper.configure(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);
    objectMapper.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true);
    
    return objectMapper.readValue(jsonStr, CarDto.class);
}

场景2:用文档ID构造业务对象

如果原Json.newDocument(documentId)是想把ID作为业务对象的一部分,直接构造DTO即可:

public CarDto get(String documentId) {
    // 从存储获取车辆数据,或直接构造DTO
    CarDto dto = fetchCarDataFromStorage(documentId);
    dto.setId(documentId); // 将文档ID设置到DTO对应字段
    return dto;
}

3. 确保特殊字符的JSON合法性

如果需要将含#的字符串作为JSON值,必须用Jackson生成合法的JSON字面量:

// 生成包含特殊字符ID的合法JSON
String validJson = objectMapper.writeValueAsString(Map.of("id", documentId));

关键注意事项

  • 彻底移除项目中OJAI相关的依赖包,避免类路径冲突
  • 所有JSON处理统一使用Jackson API,保持逻辑一致性
  • 针对含特殊字符的文档ID场景做专项测试,验证JSON解析与生成的合法性

内容的提问来源于stack exchange,提问作者Peter Penzov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:11:25