Davyzhu Davyzhu - 1 year ago 131
Java Question

How to extract part of the *original* text from JSON?

PLEASE, don't edit the question for me. My question is on String manipulation, changing the flow of text can very likely change the meaning of the question and cause confusion.

The problem can be viewed as a String manipulation problem. But I expect a solution in Jackson to solve my problem.

Suppose I have received a String

. When it's displayed, it's like:

"payload": {
"foo": "bar",
"ipsum": [
"signature": "somehmacsign"

How can I extract its substring from 11th character
till the
just before
. Namely,
. Semantically, I want to extract the original string representation for the
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.

Thanks in advance!

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

EDIT2: 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.

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

Thanks for all that participated!

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

Answer Source

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.

Creating a custom deserializer

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

public class RawJsonDeserializer extends JsonDeserializer<String> {

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

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

        String json = jp.getCurrentLocation().getSourceRef().toString();
        return json.substring((int) begin - 1, (int) end);

Creating a Java class to hold the values

Create a Java class to hold the values (pay attention to the @JsonDeserialize annotation):

public class Request {

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

    private String signature;

    // Getters and setters ommitted

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\"," +

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

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

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download