【问题标题】:How to Handle JsonSyntaxException when Receiving Response from GAE收到GAE响应时如何处理JsonSyntaxException
【发布时间】:2016-01-28 17:56:04
【问题描述】:

我正在尝试使用 Retrofit 而不是 AsyncTask 复制 Google App Engine Servlets 模块 here

我觉得这很奇怪,但显然 Retrofit 2.0 不支持与 Google App Engine 的连接,正如 GitHub 存储库问题中的 here 所述。

因此,我使用的是 Retrofit 1.9 和 OkHttp 2.3 依赖项。

我在 Google Developer Console 中创建了一个名为“Retrofit Test”的项目,Google 为我提供了该项目的 URL:“http://retrofit-test-1203.appspot.com”,子域为“http://retrofit-test-1203.appspot.com/hello。这些将是我各自的改造的 URL。下面是我的代码:

分级:

apply plugin: 'com.android.application'

android {
compileSdkVersion 23
buildToolsVersion "23.0.1"

defaultConfig {
    applicationId "com.troychuinard.retrofittest"
    minSdkVersion 16
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
 } 
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.squareup.okhttp:okhttp:2.3.0'


}

主活动:

public class MainActivity extends AppCompatActivity {

//set the URL of the server, as defined in the Google Servlets Module Documentation
private static String PROJECT_URL = "http://retrofit-test-1203.appspot.com";
private Button mTestButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    mTestButton = (Button) findViewById(R.id.test_button);



    //Instantiate a new UserService object, and call the "testRequst" method, created in the interface
    //to interact with the server
    mTestButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Instantiate a new RestAdapter Object, setting the endpoint as the URL of the server
            RestAdapter restAdapter = new RestAdapter.Builder()
                    .setEndpoint(PROJECT_URL)
                    .setClient(new OkClient(new OkHttpClient()))
                    .build();

            UserService userService = restAdapter.create(UserService.class);
            userService.testRequest("Test_Name", new Callback<String>() {
                @Override
                public void success(String s, Response response) {
                    Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();

                }

                @Override
                public void failure(RetrofitError error) {
                    Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();
                }
            });
        }
    });


   }
}

用户服务(改造)

public interface UserService {

@POST("/hello")
void testRequest(@Query("name") String name, Callback<String> cb);

}

我的 Servlet:

public class MyServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
    resp.setContentType("text/plain");
    resp.getWriter().println("Please use the form to POST to this url");
}

@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
    String name = req.getParameter("name");
    resp.setContentType("text/plain");
    if(name == null) {
        resp.getWriter().println("Please enter a name");
    }
    resp.getWriter().println("Hello " + name);
  }
}

如您所见,我已经设置了项目,以便在单击按钮时发出服务器请求。与 Google App Engine Servlets 模块类似,我希望收到来自服务器的响应,然后我将其显示为一个 Toast,上面写着“Hello +(输入 .testRequest() 方法中的任何参数,即“Test_Name”)这种情况。我收到以下错误,感谢您对我的方法提供任何帮助/建议:

【问题讨论】:

    标签: java android google-app-engine servlets retrofit


    【解决方案1】:

    这里的问题是您尝试发送带有“名称”参数的 POST 作为 @Query,而您应该发送为 @Field

    试试这样的方法:

    @FormUrlEncoded
    @POST("/hello") 
    void testRequest(@Field("name") String name, Callback<String> cb);
    

    【讨论】:

    • 当我更改为 @Field 时,我仍然收到与图片中指示的完全相同的错误
    【解决方案2】:

    您返回的是纯文本响应,并且从错误消息中我假设 Retrofit 需要 JSON 格式的响应。要么:

    • 尝试将resp.setContentType("text/plain");更改为resp.setContentType("application/json");并将内容更改为JSON格式

    • 或检查此问题以从响应中读取字符串:Retrofit callback get response body

    【讨论】:

    • 当您说将内容更改为JSON格式时,您指的是什么(除了您提供的代码sn-p)?
    • servlet 返回一个纯字符串,如"Hello " + name。这不是 JSON 格式。我不确定预期的格式是什么,但一个示例 JSON 看起来像 "{ \"response\": \"Hello" + name + "\"}",它将呈现为 { "response": "Hello World" }
    • 谢谢!我将不得不玩弄它。我的最终目标是用 Retrofit 替换 AsyncTask,因为 AsyncTask 似乎已经过时了。 Google App Engine 的文档有限,我认为改造会更容易,但事实并非如此。
    • 老实说,这似乎与您使用的客户端库/框架(AsyncTask vs Retrofit)相比,App Engine 更像是一个 Java servlet 容器,以及任何通用的有关如何实现 Java Servlets 的文档/教程很有帮助。
    • 你能指出一些相关文档的正确方向吗?
    猜你喜欢
    • 2023-03-20
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多