如何从杰克逊的JSON中提取部分*原始*文本?

Dav*_*zhu 2 java json jackson

请不要为我编辑问题.我的问题是关于字符串操作,改变文本流很可能会改变问题的含义并引起混淆.

该问题可以视为字符串操作问题.但我希望杰克逊能够解决我的问题.


假设我收到了一个字符串{"payload":{"foo":"bar","ipsum":["lorem","lorem"]},"signature":"somehmacsign"}.当它显示时,它就像:

{
    "payload": {
        "foo": "bar",
        "ipsum": [
            "lorem",
            "lorem"
        ]
    },
    "signature": "somehmacsign"
}
Run Code Online (Sandbox Code Playgroud)

如何从第11个字符中提取其子字符串{直到}前一个字符串,"signature".即,{"foo":"bar","ipsum":["lorem","lorem"]}.从语义上讲,我想提取字段的原始字符串表示payload.我想它不应该涉及将JSON字符串解析为Java对象并返回String.我不想冒失去字段,间距或任何小功能的顺序的风险,因为它意味着HMAC签名.


编辑1:重新说明这个问题与Java String文字无关.

编辑2:虽然说起来可能有点早,但我的问题一般没有明显的现成解决方案(如何部分提取/解析JSON字符串).事实上,我自己发现我的懒惰/部分解析理论有点冗长.它需要太多的传递来定位深度嵌套的节点.

特别是对于我的情况,我发现在请求正文中附加签名是一个坏主意,因为它给接收方带来了困难.我正在考虑将签名移动到HTTP标头,也许X-Auth-Token

编辑3:事实证明,我的结论太早了.Cassio的答案通过使用自定义反序列化器和魔法完美地解决了这个问题skipChildren!

cas*_*lin 8

您可以将签名移动到HTTP标头以使事情更简单.

但是,如果要将签名保留在请求有效内容中,请执行以下步骤.

创建自定义反序列化程序

创建一个可以获取原始JSON字符串值的自定义反序列化器:

public class RawJsonDeserializer extends JsonDeserializer<String> {

    @Override
    public String deserialize(JsonParser jp, DeserializationContext ctxt)
           throws IOException, JsonProcessingException {

        long begin = jp.getCurrentLocation().getCharOffset();
        jp.skipChildren();
        long end = jp.getCurrentLocation().getCharOffset();

        String json = jp.getCurrentLocation().getSourceRef().toString();
        return json.substring((int) begin - 1, (int) end);
    }
}
Run Code Online (Sandbox Code Playgroud)

创建一个Java类来保存值

创建一个Java类来保存值(注意@JsonDeserialize注释):

public class Request {

    @JsonDeserialize(using = RawJsonDeserializer.class)
    private String payload;

    private String signature;

    // Getters and setters ommitted
}
Run Code Online (Sandbox Code Playgroud)

解析JSON

使用解析JSON ObjectMapper,Jackson将使用您在上面定义的解串器:

String json = "{\"payload\":{\"foo\":\"bar\",\"ipsum\":[\"lorem\"," +
              "\"lorem\"]},\"signature\":\"somehmacsign\"}";

ObjectMapper mapper = new ObjectMapper();
Request request = mapper.readValue(json, Request.class);
Run Code Online (Sandbox Code Playgroud)

如果payload是无效的JSON,杰克逊将抛出异常.

  • 优秀!这是我一直在寻找的答案.非常有启发性,谢谢! (2认同)