RETROFIT 如何解析此响应

2024-04-22

我正在尝试解析这个 json 响应雅虎YQL http://chartapi.finance.yahoo.com/instrument/1.0/goog/chartdata;type=quote;range=1d/json使用 Retrofit,但问题是响应以以下字符开始(如您在上面的链接中看到的):“finance_charts_json_callback(”。

因此我收到以下错误:com.google.gson.JsonSyntaxException:java.lang.IllegalStateException:预期为 BEGIN_OBJECT,但在第 1 行第 1 列路径 $ 处为 STRING .

可以用Retrofit解析这个json文件吗? 提前致谢


它返回一个由回调函数 (jsonp) 调用的 json。去掉函数包装器并解析它,或者调用不基于 jsonp 的端点(如果可用)。

Update1:

以下是如何使用正则表达式将 jsonp 响应转换为 json 的示例:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by jamesanto on 12/22/15.
 */
public class JsonpParser {

    private static final Pattern JSONP = Pattern.compile("(?s)\\w+\\((.*)\\).*");

    public static String jsonpToJson(String jsonStr) {
        Matcher matcher = JSONP.matcher(jsonStr);
        if(matcher.find()) {
            return matcher.group(1);
        } else {
            throw new IllegalArgumentException("Unknown jsonp format");
        }
    }

    public static void main(String[] args) {
        String sampleJson = "finance_charts_json_callback({\n" +
                "    \"base\": \"cmc stations\",\n" +
                "    \"clouds\": {\n" +
                "        \"all\": 75\n" +
                "    },\n" +
                "    \"cod\": 200,\n" +
                "    \"coord\": {\n" +
                "        \"lat\": 51.51,\n" +
                "        \"lon\": -0.13\n" +
                "    },\n" +
                "    \"dt\": 1450807548,\n" +
                "    \"id\": 2643743,\n" +
                "    \"main\": {\n" +
                "        \"humidity\": 82,\n" +
                "        \"pressure\": 1011,\n" +
                "        \"temp\": 286.94,\n" +
                "        \"temp_max\": 287.59,\n" +
                "        \"temp_min\": 286.15\n" +
                "    },\n" +
                "    \"name\": \"London\",\n" +
                "    \"sys\": {\n" +
                "        \"country\": \"GB\",\n" +
                "        \"id\": 5091,\n" +
                "        \"message\": 0.0136,\n" +
                "        \"sunrise\": 1450771468,\n" +
                "        \"sunset\": 1450799652,\n" +
                "        \"type\": 1\n" +
                "    },\n" +
                "    \"weather\": [\n" +
                "        {\n" +
                "            \"description\": \"light rain\",\n" +
                "            \"icon\": \"10n\",\n" +
                "            \"id\": 500,\n" +
                "            \"main\": \"Rain\"\n" +
                "        },\n" +
                "        {\n" +
                "            \"description\": \"light intensity drizzle rain\",\n" +
                "            \"icon\": \"09n\",\n" +
                "            \"id\": 310,\n" +
                "            \"main\": \"Drizzle\"\n" +
                "        }\n" +
                "    ],\n" +
                "    \"wind\": {\n" +
                "        \"deg\": 210,\n" +
                "        \"gust\": 14.9,\n" +
                "        \"speed\": 9.8\n" +
                "    }\n" +
                "});";


        String json = jsonpToJson(sampleJson);
        System.out.println(json);
    }
}

更新2:

我已经扩展了现有的 GsonConverterFactory 以支持 jsonp。

//JsonpGsonResponseBodyConverter.java

package retrofit;

import com.google.gson.Gson;
import com.squareup.okhttp.ResponseBody;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;

final class JsonpGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  private final Gson gson;
  private final Type type;

  JsonpGsonResponseBodyConverter(Gson gson, Type type) {
    this.gson = gson;
    this.type = type;
  }

  private static String readerToString(Reader reader) throws IOException {
    StringBuilder builder = new StringBuilder();
    int charsRead = -1;
    char[] chars = new char[100];
    do{
      charsRead = reader.read(chars,0,chars.length);
      //if we have valid chars, append them to end of string.
      if(charsRead>0)
        builder.append(chars,0,charsRead);
    }while(charsRead>0);
    return builder.toString();
  }

  @Override public T convert(ResponseBody value) throws IOException {
    Reader reader = value.charStream();
    try {
      String jsonp = readerToString(reader);
      String json = JsonpParser.jsonpToJson(jsonp);
      return gson.fromJson(json, type);
    } finally {
      Utils.closeQuietly(reader);
    }
  }
}

//JsonpGsonConverterFactory.java

package retrofit;

import com.google.gson.Gson;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.ResponseBody;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

/**
 * A {@linkplain Converter.Factory converter} which uses Gson for JSON.
 * <p>
 * Because Gson is so flexible in the types it supports, this converter assumes that it can handle
 * all types. If you are mixing JSON serialization with something else (such as protocol buffers),
 * you must {@linkplain Retrofit.Builder#addConverterFactory(Converter.Factory) add this instance}
 * last to allow the other converters a chance to see their types.
 */
public final class JsonpGsonConverterFactory extends Converter.Factory {
  /**
   * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  public static JsonpGsonConverterFactory create() {
    return create(new Gson());
  }

  /**
   * Create an instance using {@code gson} for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  public static JsonpGsonConverterFactory create(Gson gson) {
    return new JsonpGsonConverterFactory(gson);
  }

  private final Gson gson;

  private JsonpGsonConverterFactory(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    this.gson = gson;
  }

  @Override
  public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {
    return new JsonpGsonResponseBodyConverter<>(gson, type);
  }

  @Override public Converter<?, RequestBody> toRequestBody(Type type, Annotation[] annotations) {
    return new GsonRequestBodyConverter<>(gson, type);
  }
}

现在,在构建服务时,将上述转换器注册为转换器,如下所示:

Retrofit retrofit = new Retrofit.Builder()
                    .setEndpoint("<yahoo api url>").setConverter(JsonpGsonConverterFactory.create())
                    .build();

更新3:

“GsonRequestBodyConverter”类已经带有以下依赖项,但为了完整起见,我将其添加到此处:

“com.squareup.retrofit”%“转换器-gson”%“2.0.0-beta2”

package retrofit;

import com.google.gson.Gson;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.RequestBody;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import okio.Buffer;

final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
  private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
  private static final Charset UTF_8 = Charset.forName("UTF-8");

  private final Gson gson;
  private final Type type;

  GsonRequestBodyConverter(Gson gson, Type type) {
    this.gson = gson;
    this.type = type;
  }

  @Override public RequestBody convert(T value) throws IOException {
    Buffer buffer = new Buffer();
    Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
    try {
      gson.toJson(value, type, writer);
      writer.flush();
    } catch (IOException e) {
      throw new AssertionError(e); // Writing to Buffer does no I/O.
    }
    return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
  }
}

最后是缺失的“Utils”:

package retrofit;

import java.io.Closeable;
import java.io.IOException;

/**
 * Created by jamesanto on 12/23/15.
 */
public final class Utils {
    static void closeQuietly(Closeable closeable) {
        if (closeable == null) return;
        try {
            closeable.close();
        } catch (IOException ignored) {
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RETROFIT 如何解析此响应 的相关文章

  • SpinnerAdapter 中 getView 和 getDropDownView 的区别

    当你实现 SpinnerAdapter 时 你会得到获取下拉视图 http developer android com reference android widget SpinnerAdapter html getDropDownView
  • 在 Java/Android 中检查字符串是否包含 URL 的最佳方法是什么?

    在 Java Android 中检查字符串是否包含 URL 的最佳方法是什么 最好的方法是检查字符串是否包含 com net org info 其他 或者有更好的方法吗 url 输入到 Android 中的 EditText 中 它可以是粘
  • Android 4.3 虚拟设备 CPU/ABI - 未安装系统映像(eclipse)

    I m trying to set up a new device but I can not continue with the process I think it s because the target version is 4 3
  • Android布局中如何实现Button的自动宽度

    我有几个垂直列出的按钮 我需要它们都具有相同的宽度 而且还要显示其中的所有文本 基本上我需要所有它们的宽度作为最大的宽度的包裹宽度 希望我解释得很好 现在 我已经有一种布局可以在我的 Samsung Galaxy S2 4 1 2 上运行
  • 我无法从 Android 模拟器中删除日语 IME

    我已经多次看到这个问题 但答案总是 从 语言和键盘设置 菜单中取消选中 IME 问题是那里没有复选框 选择菜单 自定义区域设置 en US 菜单 设置 语言和键盘 选择语言 选择 英语 美国 菜单 设置 语言和键盘 日语输入法是唯一的输入法
  • 删除所有(子)片段的正确方法

    我在父级片段线性布局 fragmentContainer 中动态加载一堆子级片段 然后当用户单击按钮时 我需要将它们全部删除并添加新的 我不知道每次会添加多少碎片 这是我一次性删除所有碎片的方法 LinearLayout ll Linear
  • Android - 在通知栏中使用外部个人资料图像,如 Facebook

    我知道您可以在推送通知参数中发送信息 例如消息 标题 图像 URL 等 Facebook 如何在通知区域中显示您的个人资料图片和消息 我想在通知区域中使用外部图像 因此当您将其下拉时 您会看到带有消息的个人资料图像 现在 我的仅显示可绘制文
  • Android 3.1 USB 主机 - BroadcastReceiver 未收到 USB_DEVICE_ATTACHED

    我经历过USB 主机的描述和示例位于developer android com http developer android com guide topics usb host html检测连接和分离的 USB 设备 如果我在清单文件中使用
  • 将侦听器添加到各个 ListPreference 项

    我正在尝试将单个侦听器添加到ListPreference但我只是找不到正确的代码来做到这一点 例如 假设我有一个应用程序需要region要设置 所以我有一个ListPreference有三个选项 美洲 亚洲 欧洲 当我使用触控板滚动浏览项目
  • Android:Google Maps API 密钥注册:MD5 认证密钥

    如何获取MD5指纹密钥 我正在使用这个命令 C Program Files Java jdk1 7 0 04 bin gt keytool exe list alias androiddebugkey keystore C Document
  • 如何在Android上获取角度中的按键事件?

    我们如何在 Android 上的 Angular 中获取按键事件及其值 我使用phonegap Cordova Angular JS
  • 改造添加带有令牌和 ID 的标头

    我在获取经过身份验证的用户时遇到问题 在此之前我得到了令牌和用户 ID 现在我需要使用访问令牌和 ID 从服务器获取用户 我有标题格式 https i stack imgur com OQ87Y png 现在我尝试使用拦截器添加带有用户令牌
  • 改变换行行为

    我可以在 TextView 中使用 Spannable 创建具有不同外观 下划线 删除线等的跨度 我怎样才能做同样的事情来改变换行行为 特别是 我不希望电子邮件地址在中间换行 我希望它像一个单词一样 I tried 包裹在一起跨度 http
  • IllegalStateException:无法更改片段的标签,以前是 android:switcher,现在是 android:switcher

    我的活动使用TabLayout ViewPager 这里的选项卡和页面的数量是动态的 具体取决于从服务器获取的数据 崩溃是通过 Crashlytics 报告的 我无法复制它 我的活动代码 Override protected void on
  • 在 WebView 中打开 PDF 文件

    大约 2 天 我尝试在我的自定义中打开 PDF 文件WebvView 这是我的WebView code import android app AlertDialog import android app ProgressDialog imp
  • android中ScrollView中的图像

    在我的应用程序中 我想放置一个 png 文件 并且希望它在横向和纵向模式下都被视为滚动图像 请建议代码或示例 要使您的 Imageview 在高度不适合时滚动 您可以在 xml 中的 ScrollView 内添加一个 ImageView 并
  • libgdx SpriteBatch 渲染到纹理

    是否可以使用 libGdx 适用于 Android 桌面的 Java 引擎 中的 SpriteBatch 渲染到纹理 如果是这样 怎么办 基本上我想将所有内容渲染到 512 x 256 纹理的 320 x 240 区域 然后缩放区域以适合屏
  • 如何从 SD 卡中删除文件

    我正在创建一个文件作为电子邮件的附件发送 现在我想在发送电子邮件后删除图像 有没有办法删除文件 我努力了myFile delete 但它没有删除该文件 我在 Android 上使用此代码 因此编程语言是 Java 使用通常的 Android
  • SWIG C 函数指针和 JAVA

    我有一些 C 代码 其中一个方法有一个函数指针作为参数 我正在尝试在我的 Android 应用程序中使用 C 代码 我决定使用 SWIG 来完成生成我需要的 java 文件的所有工作 一切都适用于常规函数 没有函数指针作为参数的函数 但我不
  • 如何使用Android Invalidate()

    在我的主要活动中 我定义了两个视图和一个菜单 浏览次数 1 自定义视图游戏 2 按钮btn 菜单 1 打开项目用于打开文件 菜单布局在不同的活动中定义 基本上 当主活动启动时 它会绘制没有任何内容的自定义视图和按钮 然后我使用菜单中的 打开

随机推荐

  • 与 INADDR_ANY 绑定

    如果我将套接字绑定到 INADDR ANY 我知道它将接受服务器上配置的任何 IP 上的传入连接 假设我在进行 bind 调用时配置了 1 个 IP 然后配置了一个新的 IP bind 是否也会接受向新配置的 IP 发起的连接 还是仅适用于
  • Aurelia 自定义属性中的双向绑定

    UPDATE 看起来这是一个已知的错误 https github com aurelia templated issues 253 https github com aurelia templating issues 253我将其留在这里是
  • 在项目 .d.ts 定义文件中使用 @types 定义

    我正在尝试为我的项目编写一个 d ts 文件来定义一些全局接口 但是 我在该定义文件中使用非全局库类型时遇到问题 特别是我试图引用的 RxJs 对我来说不起作用 我认为最有效的方法是使用三斜杠引用标签来导入 RxJ 的类型 但这不起作用
  • Masonry 插件:调整 div 大小不会导致重新洗牌

    将 Masonry 项目包裹在 1000px 宽的 div 中 我有一个按钮可以使用 jQuery 将 div 大小调整为 2000xaddClass 问题是 Masonry 不会重新排列项目来填充额外的 1000px 空间 我知道调整大小
  • PageViewController - 将变量传递给子视图

    我拥有的 我有一个 ViewController TutorialViewController 和一个 UIPageViewController TutorialPageViewController 故事板上还有 3 个带有 StoryBo
  • Paramiko 和伪 tty 分配

    我正在尝试使用 Paramiko 连接到远程主机并执行许多文本文件替换 i o e client exec command perl p i e s initial replaced g conf 其中一些命令需要作为 sudo 运行 这会
  • 用于创建工作项模板的 TFS 客户端 API?

    当然 很可能在 TFS 中创建工作项 获取工作项列表等 除此之外 我们还需要具有允许用户为各种文件类型创建自己的工作项模板的功能 TFS 客户端 API 是否能够将工作项模板上传到 TFS 服务器 有一种方法可以获取 XML 定义 Micr
  • 在函数内调用 div

    我正在尝试使用 jQuery mobile 1 4 3 创建一个类似于 iOS 警报视图的弹出窗口 我需要从 javascript 事件触发警告消息 例如带有 确定 按钮的确认消息 显示对 Web 服务的 ajax 响应调用 我的第一个问题
  • # jquery移动页面url中的字符

    为什么当我访问我的 jQuery 移动页面时 假设 page php 显示正常 但当我访问同一页面 page php someDetailsHere 时 它 只显示一个白色页面 我该如何解决这个问题 我使用第三方应用程序重定向到我的网页 添
  • 通过 Kafka 消费者重试维持订单保证

    我正在为基于 Kafka 的数据处理管道中的消费者重试设计一个架构 我们正在使用 Kafka 生产者和消费者 并且正在考虑重试主题 如果消费出错 将在这些主题上发送消息 将会有消费者以一定的节奏运行这些重试主题 我读了很多参考架构 但没有一
  • 渲染图表后,从图表对象更改 Highcharts 工具提示格式化程序

    我发现我可以使用 setData 更改系列 并且我知道我可以使用 setExtremes 修改最大值 但我无法弄清楚如何从图表对象设置工具提示格式化程序 我如何更新该字段 如果我有一个图表对象 如何更新其工具提示格式化程序属性 以及plot
  • 如何让我的收据不再重复

    这是一个程序 要求用户输入条形码 然后我的程序找到指定的产品 询问用户他们想要购买多少产品 如果他们想继续 计算总价 然后假设打印出收据 但是我的问题是收据重复其值并且没有四舍五入到小数点后两位 press 0 to stop shoppi
  • 如何在postgreSQL命令中指示在哪个数据库中执行脚本? (类似于SQL Server“use”命令)

    我有以下问题 我需要放入一个在新版本推出之前运行的脚本 该脚本在 PostgreSQL 中启用 pgAgent 的 SQL 代码 但是 此代码应该在维护数据库 postgres 上运行 而我们运行脚本文件的数据库是另一个数据库 我记得在 S
  • 如何检测视频标签上播放的视频的帧速率?

    有什么方法可以通过 javascript 检测视频 html5 标签中引用的视频的帧速率是多少 我还在寻找比特率和编解码器信息 因为 html5 视频播放器与编解码器无关 thanks FPS 存储在video文件的标题 这是您正在寻找的实
  • 使用 Swift array.count 和 arc4random()

    为了让这段代码正常工作 我缺少什么 NodesLeft 是一个 Int let x nodesLeft count let r Int arc4random uniform x 我收到错误 Playground 执行失败 错误 136 40
  • Javascript:在数组末尾重新启动一次循环

    我最近遇到了这个问题 但在任何地方都找不到好的答案 因此有这个问题 我想在到达终点后重新启动循环 但只循环有限的次数 在这个特定的上下文中 我一周中有一系列天 我想使用以下命令显示从今天开始的接下来 7 天的日期名称Date getDay
  • 为什么 C++ 编译器对许多大括号的处理方式不同?

    在下面的 C 20 程序中 我错误地添加了一对额外的弯曲大括号 in B A include
  • 如何在样式组件中访问 Material-ui 的主题

    我将 CRA 与 Material ui 和 Styled Components 类型的样式一起使用 在构建 CSS 时 我想访问 Material ui 的默认主题 package json 的一部分 dependencies react
  • 两点层之间的距离矩阵

    我有两个数组 其中包含不同大小的点坐标 shapely geometry Point Eg Point X Y Point X Y Point X Y Point X Y 我想用距离函数创建这两个数组的 叉积 距离函数来自shapely g
  • RETROFIT 如何解析此响应

    我正在尝试解析这个 json 响应雅虎YQL http chartapi finance yahoo com instrument 1 0 goog chartdata type quote range 1d json使用 Retrofit