How to handle Dynamic JSON in Retrofit?

后端 未结 10 2244
余生分开走
余生分开走 2020-11-22 16:23

I am using the retrofit efficient networking library, but I am unable to handle Dynamic JSON which contains single prefix responseMessage which changes to

相关标签:
10条回答
  • Late to the party, but you can use a converter.

    RestAdapter restAdapter = new RestAdapter.Builder()
        .setEndpoint("https://graph.facebook.com")
        .setConverter(new DynamicJsonConverter()) // set your static class as converter here
        .build();
    
    api = restAdapter.create(FacebookApi.class);
    

    Then you use a static class which implements retrofit's Converter:

    static class DynamicJsonConverter implements Converter {
    
        @Override public Object fromBody(TypedInput typedInput, Type type) throws ConversionException {
            try {
                InputStream in = typedInput.in(); // convert the typedInput to String
                String string = fromStream(in);
                in.close(); // we are responsible to close the InputStream after use
    
                if (String.class.equals(type)) {
                    return string;
                } else {
                    return new Gson().fromJson(string, type); // convert to the supplied type, typically Object, JsonObject or Map<String, Object>
                }
            } catch (Exception e) { // a lot may happen here, whatever happens
                throw new ConversionException(e); // wrap it into ConversionException so retrofit can process it
            }
        }
    
        @Override public TypedOutput toBody(Object object) { // not required
            return null;
        }
    
        private static String fromStream(InputStream in) throws IOException {
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            StringBuilder out = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                out.append(line);
                out.append("\r\n");
            }
            return out.toString();
        }
    }
    

    I have written this sample converter so it returns the Json response either as String, Object, JsonObject or Map< String, Object >. Obviously not all return types will work for every Json, and there is sure room for improvement. But it demonstrates how to use a Converter to convert almost any response to dynamic Json.

    0 讨论(0)
  • 2020-11-22 17:08

    I know I am late, but I just want to share my thought. I was working on a project where I am writing a method. The method uses retrofit to get data from server. Since other developers in my company will use this method, I could not use a POJO class (in your example, the TrackerRefResponse class). So I used JsonObject / Object like this:

    interface APIService.java

    public class APIService{
        @FormUrlEncoded
        @POST
        Call<JsonObject> myPostMethod(@Url String url, @Field("input") String input);
    }
    

    Then in my method, I wrote this:

    Call<JsonObject> call = RetrofitClient.getAPIService().establishUserSession(post_request_url, someParameter);
    
    call.enqueue(new Callback<JsonObject>() {
                @Override
                public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
                    JsonObject jsonObject = response.body();
                    String jsonString = response.body().toString();
                    // then do your stuff. maybe cast to object using a factory pattern  
        }
    // rest of the code
    }
    
    

    You can also use Object instead of 'JsonObject`. Later, when you will know which kind of response it is, maybe you can cast this into desired object.

    0 讨论(0)
  • 2020-11-22 17:09

    RestClient.java

    import retrofit.client.Response;
    public interface RestClient {
      @GET("/api/foo") Response getYourJson();
    }
    

    YourClass.java

    RestClient restClient;
    
    // create your restClient
    
    Response response = restClient.getYourJson();
    
    Gson gson = new Gson();
    String json = response.getBody().toString();
    if (checkResponseMessage(json)) {
      Pojo1 pojo1 = gson.fromJson(json, Pojo1.class);
    } else {
      Pojo2 pojo2 = gson.fromJson(json, Pojo2.class);
    }
    

    You must implement "checkResponseMessage" method.

    0 讨论(0)
  • Any of your possible solutions will work. What you can also do is send the Retrofit api interface return type to response. With that response you get a body Inputstream which you can convert to a JSON Object and read as you see fit.

    Look at: http://square.github.io/retrofit/#api-declaration - under RESPONSE OBJECT TYPE

    Updated

    Retrofit 2 is out now and with it some changes to the documentation and library.

    Look at http://square.github.io/retrofit/#restadapter-configuration there are request and response body object that can be used.

    0 讨论(0)
提交回复
热议问题