【问题标题】:Spring - Return Raw JSON without double serializationSpring - 返回原始 JSON 而不进行双重序列化
【发布时间】:2019-03-10 05:20:18
【问题描述】:

我知道还有其他类似的帖子,但我没有找到任何可以帮助我找到解决这个特殊案例的解决方案的帖子。

我正在尝试从我的控制器返回 HashMap<String, Object>Object 部分是一个 JSON 字符串,但它被双重序列化并且不作为原始 JSON 字符串返回,因此不会以额外的引号和转义字符结束。

控制器功能:

@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public HashMap<String, Object> heartbeat(){
    String streamInfo = service.getStreamInfo();
    String streamCursorInfo = service.getStreamCursorInfo();
    String topicInfo = service.getTopicInfo();

    String greeting = "This is a sample app for using Spring Boot with MapR Streams.";

    HashMap<String, Object> results = new HashMap();
    results.put("greeting", greeting);
    results.put("streamInfo", streamInfo);
    results.put("streamCursorInfo", streamCursorInfo);
    results.put("topicInfo", topicInfo);

    return results;
}

服务功能:

private String performCURL(String[] command){
    StringBuilder stringBuilder = new StringBuilder();

    try{
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        Process p = processBuilder.start();

        BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line = null;
        while((line = reader.readLine()) != null){
            stringBuilder.append(line);
        }
    }
    catch(Exception e){
        LOGGER.error(ExceptionUtils.getRootCauseMessage(e));
    }

    return stringBuilder.toString();
}

我运行的 cURL 命令已经返回一个原始 JSON 字符串。所以我只是试图将它添加到 HashMap 以在心跳响应中返回。

但是每次我运行这个,我的输出看起来像:

{
"greeting": "This is a sample app for using Spring Boot with MapR Streams.",
"streamCursorInfo": "{\"timestamp\":1538676344564,\"timeofday\":\"2018-10-04 02:05:44.564 GMT-0400 PM\",\"status\":\"OK\",\"total\":1,\"data\":[{\"consumergroup\":\"MapRDBConsumerGroup\",\"topic\":\"weightTags\",\"partitionid\":\"0\",\"produceroffset\":\"44707\",\"committedoffset\":\"10001\",\"producertimestamp\":\"2018-10-03T05:57:27.128-0400 PM\",\"consumertimestamp\":\"2018-09-21T12:35:51.654-0400 PM\",\"consumerlagmillis\":\"1056095474\"}]}",
...
}

如果我只返回单个字符串,例如streamInfo,那么它可以正常工作并且不会添加额外的引号和转义字符。

谁能解释我缺少什么或需要做些什么来防止这种双重序列化?

【问题讨论】:

    标签: json spring-mvc spring-boot jackson


    【解决方案1】:

    不要返回HashMap,而是创建一个像这样的对象:

    public class HeartbeatResult {
      private String greeting;
      ... //other fields here
    
      @JsonRawValue
      private String streamCursorInfo;
    
      ... //getters and setters here (or make the object immutable by having just a constructor and getters)
    }
    

    @JsonRawValue Jackson 将按原样序列化字符串。请参阅https://www.baeldung.com/jackson-annotations 了解更多信息。

    【讨论】:

    • 谢谢,效果很好。我之前看过@JsonRawValue 注释,但不确定它的确切用途,我试图找到一个不需要我为响应而制作额外类文件的解决方案。但这暂时可行。
    【解决方案2】:

    streamCursorInfo 是一个字符串,而不是一个对象 => 序列化将转义 " 字符。

    如果您能够返回包含数据的对象,它将开箱即用。如果您拥有的只是一个字符串,我建议将其序列化为 JsonNode 并将其添加到您的响应中

    ObjectMapper objectMapper = new ObjectMapper();
    
    JsonNode streamCursorInfo = objectMapper.readTree(service.getStreamInfo())
    
    results.put("streamCursorInfo", streamCursorInfo);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-15
      • 1970-01-01
      • 2013-11-29
      • 2019-04-27
      • 2022-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多