【问题标题】:How to extract result content from play.mvc.Result object in play application?如何从 play 应用程序中的 play.mvc.Result 对象中提取结果内容?
【发布时间】:2014-10-10 13:55:25
【问题描述】:

实际上我正在从一个播放应用程序重定向到另一个播放应用程序,最后我收到作为 Result 对象的响应。下面是两个应用程序中的操作。我正在从应用程序 1 重定向到应用程序 2。应用程序 2 将返回我需要提取的 JSON 字符串。

如何从 Result 对象中检索 JSON 内容?

应用程序1:

public static Result redirectTest(){

    Result result =  redirect("http://ipaddress:9000/authenticate");
    /*** here I would like to extract JSON string from result***/
    return result;
}

应用程序2:

@SecuredAction
public static Result index() {
     Map<String, String> response = new HashMap<String, String>();
     DemoUser user = (DemoUser) ctx().args.get(SecureSocial.USER_KEY);

       for(BasicProfile basicProfile: user.identities){
           response.put("name", basicProfile.firstName().get());
           response.put("emailId", basicProfile.email().get());
           response.put("providerId", basicProfile.providerId());
           response.put("avatarurl", basicProfile.avatarUrl().get());
       }

    return ok(new JSONObject(response).toString());
}

【问题讨论】:

    标签: json playframework playframework-2.0


    【解决方案1】:

    使用JavaResultExtractor,例子:

    Result result = ...;
    byte[] body = JavaResultExtractor.getBody(result, 0L);
    

    拥有一个字节数组,您可以从 Content-Type 标头中提取字符集并创建 java.lang.String:

    String header = JavaResultExtractor.getHeaders(result).get("Content-Type");
    String charset = "utf-8";
    if(header != null && header.contains("; charset=")){
        charset = header.substring(header.indexOf("; charset=") + 10, header.length()).trim();
    }
    String bodyStr = new String(body, charset);
    JsonNode bodyJson = Json.parse(bodyStr);
    

    以上部分代码复制自play.test.Helpers

    【讨论】:

    • JavaResultExtractor.getBody(result, 0L) 即使我将其从 0 更改为 100k 也会超时
    • 想知道为什么不使用 play.test.Helpers.contentAsString(result) ?
    • 助手类有测试范围。
    【解决方案2】:

    我认为play.test.Helpers.contentAsString 是您正在寻找的。​​p>

    public static java.lang.String contentAsString(Result result)
    

    将内容提取为字符串。

    Play 2.8.x 仍然可用。

    【讨论】:

      【解决方案3】:

      这个功能对我来说很好用.. 感谢 Mon Calamari

      public static JsonNode resultToJsonNode(Result result) {
      
          byte[] body = JavaResultExtractor.getBody(result, 0L);
      
          ObjectMapper om = new ObjectMapper();
          final ObjectReader reader = om.reader();
          JsonNode newNode = null;
          try {
              newNode = reader.readTree(new ByteArrayInputStream(body));
              Logger.info("Result Body in JsonNode:" + newNode.toString());
          } catch (JsonProcessingException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (IOException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
      
          return newNode;
      }
      

      }

      【讨论】:

      • JavaResultExtractor.getBody 给出超时异常,即使我将值从 0 增加到 100k。
      【解决方案4】:

      您需要将 akka.stream.Materializer 的实例传递给 JavaResultExtractorgetbody 方法。

      在构造函数级别或声明级别使用 Google Guice 进行注入。

      @Inject
      Materializer materializer;
      

      此外,您还可以根据需要将 Result 转换为 String 或任何其他类型:

          Result result = getResult(); // calling some method returning result
          ByteString body = JavaResultExtractor.getBody(result, 1, materializer);
          String stringBody = body.utf8String(); // get body as String.
          JsonNode jsonNodeBody = play.libs.Json.parse(stringBody); // get body as JsonNode.
      

      【讨论】:

      • 经过一天半的搜索,这是我在 Play-2.5 上下文中“创建”“Materializer”的唯一解决方案。从 Play 2.4 到 Play 2.5 的迁移指南中确实应该提到这一点...
      【解决方案5】:

      redirect 返回错误代码为 303 的结果,这会导致调用者(浏览器)对给定的 url 执行另一个请求。
      您需要做的实际上是代理。 Application1 应该向 Application2 发出请求,并处理响应。
      Play 有很好的Web Service API 可以轻松做到这一点。

      【讨论】:

        【解决方案6】:

        在控制器方法的上下文中,您可以尝试:

        import play.libs.Json;
        import play.mvc.Result;
        import org.codehaus.jackson.JsonNode;
        import org.codehaus.jackson.node.ObjectNode;
        ...
        public static Result redirectTest(){
             ObjectNode body = (ObjectNode) request().body().asJson();
             String providerId = body.get("providerId").asText();
        }
        

        这个 SO 问题也可能有帮助:JSON and Play

        【讨论】:

          【解决方案7】:

          首先我编写了这个 scala 方法来将 Enumerator[Array[Byte]] 转换为 Future[Array[Byte]]:

          class EnumeratorHelper {
          
            def getEnumeratorFuture(body: Enumerator[Array[Byte]]) ={
              Iteratee.flatten(body |>> Iteratee.consume[Array[Byte]]()).run
            }
          
          }
          

          然后将返回的Future转换为Promise,最后得到promise值:

          final F.Promise<Result> finalResultPromise = delegate.call(ctx);
          finalResultPromise.onRedeem(result -> {
              F.Promise<byte[]> requestBodyPromise = F.Promise.wrap(new EnumeratorHelper().getEnumeratorFuture(result.toScala().body()));
          
              requestBodyPromise.onRedeem(bodyByte -> handleBody(new String(bodyByte, "UTF-8")));
          
          });
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-06-28
            • 1970-01-01
            • 2021-05-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多