本文介绍了如何使用 Jackson 从 JSON 中提取部分*原始*文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这个问题可以看作是一个字符串操作问题.但我希望杰克逊有一个解决方案来解决我的问题.

假设我收到一个字符串 {"payload":{"foo":"bar","ipsum":["lorem","lorem"]},"signature":"somehmacsign"}.显示的时候是这样的:

Suppose I have received a String {"payload":{"foo":"bar","ipsum":["lorem","lorem"]},"signature":"somehmacsign"}. When it's displayed, it's like:

{
    "payload": {
        "foo": "bar",
        "ipsum": [
            "lorem",
            "lorem"
        ]
    },
    "signature": "somehmacsign"
}

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

How can I extract its substring from 11th character { till the } just before ,"signature". Namely, {"foo":"bar","ipsum":["lorem","lorem"]}. Semantically, I want to extract the original string representation for the payload field. I suppose it should not involve parsing the JSON string to Java objects and back to String. I don't want to risk losing the order of fields, spacing, or whatever small features because it's meant to be HMAC signed.

编辑 1: 改写以澄清此问题与 Java 字符串文字无关.

EDIT 1: Rephrased to clarify that this problem has nothing to do with Java String literal.

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

EDIT 2: Though it may be a bit early to say, there is no obvious off-the-shelf solution to my question in general (how to partial extract/parse a JSON string). In fact, I myself find my lazy/partial parsing theory a bit verbose. It requires way too many of passes to locate a deeply-nested node.

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

In particular for my situation, I found appending the signature in the body of a request a bad idea as it poses difficulties for the receiving party. I'm considering moving the signature to HTTP header, maybe X-Auth-Token?

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

EDIT 3: As it turns out, I was really concluding too early. Cassio's answer perfectly solves the problem by using custom deserializer and the magic skipChildren!

推荐答案

您可以将签名移至 HTTP 标头以简化操作.

You could move the signature to a HTTP header to make things simpler.

但是,如果您想在请求负载中保留签名,请按照以下步骤操作.

However, if you want to keep the signature in the request payload, follow the steps described below.

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

Create a custom deserializer that can get the raw JSON string value:

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);
    }
}

创建一个 Java 类来保存值

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

public class Request {

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

    private String signature;

    // Getters and setters ommitted
}

解析 JSON

使用 ObjectMapper 并且 Jackson 将使用您在上面定义的反序列化器:

Parsing the JSON

Parse the JSON using ObjectMapper and Jackson will use the deserializer you have defined above:

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

ObjectMapper mapper = new ObjectMapper();
Request request = mapper.readValue(json, Request.class);

如果 payload 是无效的 JSON,Jackson 会抛出异常.

If the payload is an invalid JSON, Jackson will throw an exception.

这篇关于如何使用 Jackson 从 JSON 中提取部分*原始*文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 22:56