9

I'm writing a typical Play Framework app where I want to return a JsonNode from my Controller's methods, using Jackson.

This is how I'm doing it right now:

public static Result foo() {
   MyPojoType myPojo = new myPojo();
   String tmp = new ObjectMapper().writerWithView(JSONViews.Public.class).writeValueAsString(myPojo);
   JsonNode jsonNode = Json.parse(tmp);
   return ok(jsonNode);
}

Is it possible to avoid the "String tmp" copy and convert directly from MyPojoType to JsonNode using a view?

Maybe I can use ObjectMapper.valueToTree, but I don't know how to specify a JSonView to it.

evandongen
  • 1,995
  • 17
  • 19
Victor M.
  • 1,004
  • 8
  • 10

4 Answers4

3

Interesting question: off-hand, I don't think there is a specific method, and your code is the most straight-forward way to do it: valueToTree method does not apply any views. So code is fine as is.

StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • Thank you StaxMan. Is it too bad performance-wise? We are converting to a String, then to a full hierarchical JSonNode, and later the Play Framework converts it back again to a String. – Victor M. Apr 12 '14 at 18:38
  • It is not the most optimal -- ideally, intermediate form could be `TokenBuffer` -- but is probably not a big deal. It is possible to actually construct `TokenBuffer`, use it as `JsonGenerator` (which it extends), then use `TokenBuffer.asParser()` to get `JsonParser`, so that could be bit more efficient if you want to add couple of more lines to speed things up. – StaxMan Apr 12 '14 at 18:43
  • 1
    3 years later is there a better way now to solve this? – mkurz Jun 14 '17 at 17:00
  • I reported an issue for this: https://github.com/FasterXML/jackson-databind/issues/1687 – mkurz Jul 10 '17 at 21:29
1

After more investigation, this is what I did in the end to avoid the redundant work:

public Result toResult() {

    Content ret = null;

    try {
        final String jsonpayload = new ObjectMapper().writerWithView(JsonViews.Public.class).writeValueAsString(payload);

         ret = new Content() {
            @Override public String body() { return jsonpayload; }
            @Override public String contentType() { return "application/json"; }
        };
    } catch (JsonProcessingException exc) {
        Logger.error("toResult: ", exc);
    }

    if (ret == null)
        return Results.badRequest();

    return Results.ok(ret);
}

In summary: The methods ok, badRequest, etc accept a play.mvc.Content class. Then, simply use it to wrap your serialized json object.

Victor M.
  • 1,004
  • 8
  • 10
  • calling `writeValueAsString()` is the least efficient (why construct an intermediate String?). you should use `OutputStream` or a `Writer` – herau Oct 20 '14 at 09:29
0

As i know, with jax-rs, you can do this :

public Response toResult() throws JsonProcessingException {
    final ObjectWriter writer = new ObjectMapper()
                                    .writerWithView(JSONViews.Public.class);
    return Response.ok(new StreamingOutput() {
        @Override
        public void write(OutputStream outputStream) throws IOException, WebApplicationException {
            writer.writeValue(outputStream, /*Pojo*/ payload);
        }
    }).build();
}

So you have to find a class in the Play framework which able to stream the result (through an OutputStream)

herau
  • 1,466
  • 2
  • 18
  • 36
-4

I think this is more efficient way

public Result toResult() {
   MyPojo result = new MyPojo();
   JsonNode node = objectMapper.valueToTree(result);
   return ok(node);
}
SkyDriver
  • 65
  • 2
  • 3
    your answer doesn't take care of the subject : using a JsonView – herau Jan 13 '15 at 13:39
  • my answer does not require to serialize/deserialize object twice. And as a result from my answer you will get a JSON as a response. So please next time either learn play or at least try other's example first before you give a negative score. – SkyDriver Jan 14 '15 at 21:50
  • i'm agree with the fact that valueToTree is much efficient but the answer is incomplete. I'll leave a positive score after the review of my changes. – herau Jan 15 '15 at 08:45