bestsource

Retrofit에서 Dynamic JSON을 처리하는 방법

bestsource 2023. 3. 5. 10:13
반응형

Retrofit에서 Dynamic JSON을 처리하는 방법

만, 프리픽스 「Dynamic JSON」을 JSON을 할 수 .responseMessage 됩니다.object으로 같은 프리픽스(responseMessage는 경우에 따라 String으로 변경됩니다(동적으로).

responseMessage의 Json 형식 개체:

{
   "applicationType":"1",
   "responseMessage":{
      "surname":"Jhon",
      "forename":" taylor",
      "dob":"17081990",
      "refNo":"3394909238490F",
      "result":"Received"
   }

}

responseMessageJson j j j j j j j j j j j j j j j j j j j j j

 {
       "applicationType":"4",
       "responseMessage":"Success"          
 }

되어 있기 입니다.JSON도 동적 POJO를 .JSON응답합니다.접두사는 성공(...) 메서드와 실패(...) 메서드 모두에서 문자열에서 개체로 랜덤하게 변경됩니다.

void doTrackRef(Map<String, String> paramsref2) {
    RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint("http://192.168.100.44/RestDemo").build();



    TrackerRefRequest userref = restAdapter.create(TrackerRefRequest.class);
    userref.login(paramsref2,
            new Callback<TrackerRefResponse>() {
                @Override
                public void success(
                        TrackerRefResponse trackdetailresponse,
                        Response response) {

                    Toast.makeText(TrackerActivity.this, "Success",
                    Toast.LENGTH_SHORT).show();

                }

                @Override
                public void failure(RetrofitError retrofitError) {


                    Toast.makeText(TrackerActivity.this, "No internet",
                        Toast.LENGTH_SHORT).show();
                }


            });
}

뽀조:

public class TrackerRefResponse {


private String applicationType;

    private String responseMessage;          //String type

//private ResponseMessage responseMessage;  //Object of type ResponseMessage

//Setters and Getters


}

POJO TrackerRefResponse. response 되어 있기 할 수 있습니다: ).따라서 다이내믹 Java prefix Response Message stressage string에 대해 동일 있습니다. 가지는 POJO 를 작성할 수 있기 때문에, 다이나믹용의 같은 솔루션을 찾고 있습니다.JSON를 가진 일반 이라는 것은 REST-Api의 베스트 아닙니다.JSON해석!퍼포먼스를 보면 항상 Balley 또는 Retrofit을 선택하는 것이 가장 좋지만 다이내믹을 다루는 데 실패했습니다.JSON

가능한 해결 방법

  1. 오래된 asyc 태스크를 http 클라이언트 구문 분석과 함께 사용합니다. : (

  2. RESTAPI 백엔드 개발자를 설득합니다.

  3. 커스텀 Retrofit 클라이언트 작성 :)

파티에 늦었지만 컨버터를 사용할 수 있어요.

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);

그런 다음 개조의 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();
    }
}

이 샘플 컨버터는 String, Object, JsonObject 또는 Map < String, Object > 중 하나로 Json 응답을 반환하도록 작성되어 있습니다.모든 반품 타입이 모든 Json에 적용되는 것은 아니므로 개선의 여지가 있습니다.그러나 컨버터를 사용하여 거의 모든 응답을 동적 Json으로 변환하는 방법을 보여 줍니다.

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);
}

checkResponseMessage 메서드를 구현해야 합니다.

를 사용하여 커스텀 시도gson-converter같이 (2.) as((((ret ( Retrofit 2.0에 대한 갱신된 답변).

아래 그림과 같이 3개의 모델을 만듭니다.

응답 래퍼

public class ResponseWrapper {

    @SerializedName("applicationType")
    @Expose
    private String applicationType;
    @SerializedName("responseMessage")
    @Expose
    private Object responseMessage;

    public String getApplicationType() {
        return applicationType;
    }

    public void setApplicationType(String applicationType) {
        this.applicationType = applicationType;
    }

    public Object getResponseMessage() {
        return responseMessage;
    }

    public void setResponseMessage(Object responseMessage) {
        this.responseMessage = responseMessage;
    }

}

응답 메시지

public class ResponseMessage extends ResponseWrapper {

@SerializedName("surname")
@Expose
private String surname;
@SerializedName("forename")
@Expose
private String forename;
@SerializedName("dob")
@Expose
private String dob;
@SerializedName("refNo")
@Expose
private String refNo;
@SerializedName("result")
@Expose
private String result;

public String getSurname() {
    return surname;
}

public void setSurname(String surname) {
    this.surname = surname;
}

public String getForename() {
    return forename;
}

public void setForename(String forename) {
    this.forename = forename;
}

public String getDob() {
    return dob;
}

public void setDob(String dob) {
    this.dob = dob;
}

public String getRefNo() {
    return refNo;
}

public void setRefNo(String refNo) {
    this.refNo = refNo;
}

public String getResult() {
    return result;
}

public void setResult(String result) {
    this.result = result;
}

}

응답 문자열

public class ResponseString extends ResponseWrapper {

}

UserResponseDeserializer(커스텀디시리얼라이저)

public class UserResponseDeserializer implements JsonDeserializer<ResponseWrapper> {
@Override
public ResponseWrapper deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {


        if (((JsonObject) json).get("responseMessage") instanceof JsonObject){
            return new Gson().fromJson(json, ResponseMessage.class);
        } else {
            return new Gson().fromJson(json, ResponseString.class);
        }

}
}

Retrofit 2.0 구현

Gson userDeserializer = new GsonBuilder().setLenient().registerTypeAdapter(ResponseWrapper.class, new UserResponseDeserializer()).create();


    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("base_url")
            .addConverterFactory(GsonConverterFactory.create(userDeserializer))
            .build();


    UserService request = retrofit.create(UserService.class);
    Call<ResponseWrapper> call1=request.listAllUsers();

    call1.enqueue(new Callback<ResponseWrapper>() {
        @Override
        public void onResponse(Call<ResponseWrapper> call, Response<ResponseWrapper> response) {
            ResponseWrapper responseWrapper=response.body();
            Log.i("DYNAMIC RESPONSE", String.valueOf(response.body().getResponseMessage()));
        }

        @Override
        public void onFailure(Call<ResponseWrapper> call, Throwable t) {
        }
    });

사용된 라이브러리

com을 컴파일합니다.squareup.squarefit 2 : squarefit : 2 . 3 . 0 '

com을 컴파일합니다.squareup.fit 2: square-gson: 2.3.0'

**** 이전 답변 (위의 답변이 권장됩니다)*****

포조를 이렇게 바꾸세요.

public class TrackerRefResponse {

  private String applicationType;
  private Object responseMessage;

  public Object getResponseMessage() {
  return responseMessage;
  }

  public void setResponseMessage(Object responseMessage) {
  this.responseMessage = responseMessage;
 }
}

retrofit의 onResponse를 이렇게 변경합니다.

 @Override
public void onResponse(Response<TrackerRefResponse > response) {
    if (response.isSuccess()) {
        if (response.getResponseMessage() instanceof String)
            {
            handleStringResponse();
         }
        else 
            {
            handleObjectResponse();
         }
    }
}

동적 json 해석대한 자세한 내용은 이 게시물을 참조하십시오.

이치노Retrofit api 인터페이스 반환 유형을 응답으로 전송하는 것도 가능합니다..InputstreamJSON j j j j j j j j j j j j j j j j j j j j j.

다음 URL을 참조하십시오.http://square.github.io/retrofit/ #api - response object TYPE 。

갱신필

Retrofit 2는 현재 출시되었으며 문서와 라이브러리에 대한 몇 가지 변경 사항이 있습니다.

http://square.github.io/retrofit/ #restadapter-configuration을 참조해 주세요.사용 가능한 요청 및 응답 본문 오브젝트가 있습니다.

받아들여진 답변은 너무 복잡해 보였고, 저는 이렇게 해결했습니다.

Call<ResponseBody> call = client.request(params);
call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Response<ResponseBody> response) {
        if (response.isSuccess()) {
            Gson gson = new Gson();
            ResponseBody repsonseBody = response.body().string();
            if (isEmail) {
                EmailReport reports = gson.fromJson(responseBody, EmailReport.class);
            } else{
                PhoneReport reports = gson.fromJson(repsonseBody, PhoneReport.class);
            }
        }
    }
    @Override
    public void onFailure(Throwable t) {
        Log.e(LOG_TAG, "message =" + t.getMessage());
    }
});

이것은 다른 모델을 사용할 수 있는 방법을 보여 주기 위한 예에 불과합니다.

''isEmail는 적절한 모델을 사용하기 위한 조건의 부울일 뿐입니다.

파티에 많이 늦은 거 알아.저도 비슷한 문제가 있었는데 이렇게 해결했어요.

public class TrackerRefResponse {

    private String applicationType;
    // Changed to Object. Works fine with String and array responses.
    private Object responseMessage;

}

글자 그대로 개체로 바꿨어요.이 방법을 선택한 이유는 응답 중 하나의 필드만 동적이기 때문입니다(내 응답은 훨씬 복잡했습니다). 따라서 변환기를 사용하면 생활이 어려워질 것입니다.Gson을 사용하여 오브젝트 조작(String 값인지 Array 값인지에 따라 다름).

이것이 간단한 답을 찾는 데 도움이 되기를 바랍니다. :)

백엔드 API를 변경할 수 없는 경우에는 다음 변종(Gson을 사용하여 JSON을 변환하는 경우)을 검토하겠습니다.

  1. Gson 타입의 어댑터를 사용해, 다음의 커스텀 어댑터를 작성할 수 있습니다.ResponseMessage JSON을(inoming JSON 등).if (reader.peek() == JsonToken.STRING)를 참조해 주세요.

  2. 응답 유형을 설명하는 메타 정보를 HTTP 헤더에 삽입하고 이를 사용하여 Gson 인스턴스에 공급해야 하는 유형 정보를 결정합니다.

kotlin 개발자의 경우 변수 유형을 Any로 선언한 후 gson 컨버터를 사용하여 Gson 클래스로 변환할 수 있습니다.

data class SomeClass(
     ...somevariables,
     val respnseMessage : Any
)

그런 다음 작업 또는 조각에서 해석하여 사용할 위치를 지정합니다. 사용 사례에 따라 다음과 같은 작업을 수행할 수 있습니다.

 val gson = Gson()
 val data = gson.fromJson<YourDesireClass> 
 (response.responseMessage.toString() , YourDesireClass::class.java)

당신이 말한 것 외에...

콜백 사용 일반 get 메서드를 사용하여 필드를 가져올 수 있습니다.자세한 내용은 gson의 javadoc을 참조하십시오.

http://google-gson.googlecode.com/svn/tags/1.2.3/docs/javadocs/com/google/gson/JsonObject.html

늦은 건 알지만 내 생각을 공유하고 싶어.저는 메서드를 작성하는 프로젝트를 하고 있었습니다.이 메서드는 서버로부터 데이터를 가져오기 위해 개조를 사용합니다.우리 회사의 다른 개발자들이 이 방법을 사용할 것이기 때문에, 저는 이 방법을 사용할 수 없었습니다.POJOclass (이 예에서는TrackerRefResponse클래스)그래서 저는JsonObject/Object다음과 같습니다.

인터페이스 APIS 서비스자바

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

그리고 제 방법으로는 이렇게 썼어요.

Model1 model1 = null;
Model2 model2 = null;
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();
                // then do your stuff. maybe something like this
  try{
    model1 = new Gson().fromJson(jsonObject, Model1.class);
  }catch(Exception x){}
  try{
    model2 = new Gson().fromJson(jsonObject, Model2.class);
  }catch(Exception x){}  

  if(model1 != null) { /*handle model1 */}
  if(model2 != null) { /*handle model2*/}
 // rest of the code
}
        

특정 Attribute가 어떤 유형의 응답인지 알 수 있는 경우 JsonObject를 사용하여 해당 Atribute를 읽은 후 다음과 같이 모델을 캐스팅할 수 있습니다.

// ... retrofit codes 
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
  int number = jsonObject.get("applicationType").getAsInt();
  if(number == 1) {
    model1 = new Gson().fromJson(jsonObject, Model1.class);
  }
}
// ... rest of the code

를 사용할 수도 있습니다.Object'Json Object'가 아닌 'JsonObject.나중에 어떤 종류의 응답인지 알게 되면 원하는 오브젝트에 넣을 수 있습니다.

나도 이 문제를 다루었다.하지만 이것이 당신의 경우인지 잘 모르겠습니다.(Retrofit2를 사용하고 있습니다)

제 경우 오류와 성공 메시지를 처리해야 합니다.

성공 시

{
"call_id": 1,
"status": "SUCCESS",
"status_code": "SUCCESS",
"result": {
    "data1": {
        "id": "RFP2UjW7p8ggpMXzYO9tRg==",
        "name": "abcdef",
        "mobile_no": "96655222",
        "email": ""
    },
    "data2": [
        {
            "no": "12345"
        },
        {
            "no": "45632"
        }
    ]
}
}

오류 발생 시,

{
"call_id": 1,
"status": "FAILED",
"status_code": "NO_RECORDS",
"error": {
    "error_title": "xxx",
    "error_message": "details not found"
}
}

이것 때문에 나는 다른 POJO를 만들었다.Error ,

public class ValidateUserResponse {
@SerializedName("call_id")
public String callId;
@SerializedName("status")
public String status;
@SerializedName("status_code")
public String statusCode;
@SerializedName("result")
public ValidateUserResult result;
@SerializedName("error")
public Error error;
}

Error.java

public class Error {
@SerializedName("error_title")
public String errorTitle;
@SerializedName("error_message")
public String errorMessage;
}

ValidateUser.java

public class ValidateUserResult {

@SerializedName("auth_check")
public String authCheck;
@SerializedName("data1")
public Data1 data1;
@SerializedName("data2")
public List<Data2> data2;
}

의 .result json에는 data1,되어 있고, 그 에 json에는 data1, data2가 포함되어 있습니다.ValidateUserResult.java나면 에러가다Error.java클래스가 초기화됩니다.

다른 옵션도 검토해 주세요.

제이슨

1.
{
   "applicationType":"1",
   "responseMessage":
   {
      "surname":"Jhon",
      "forename":" taylor",
      "dob":"17081990",
      "refNo":"3394909238490F",
      "result":"Received"
   }

}

2.
 {
       "applicationType":"4",
       "responseMessage":
    {
       "forename":" taylor",
       "dob":"17081990",
    }      
 }
3.
{
       "applicationType":"5",
       "responseMessage":
    {
       "refNo":"3394909238490F",
       "result":"Received"
    }      
 }

Pojo 클래스는 다음과 같습니다.

public class ResponseMessage
{
    private String surname;

    private String forename;

    private String dob;

    private String refNo;

    private String result;

    public void setSurname(String surname){
        this.surname = surname;
    }
    public String getSurname(){
        return this.surname;
    }
    public void setForename(String forename){
        this.forename = forename;
    }
    public String getForename(){
        return this.forename;
    }
    public void setDob(String dob){
        this.dob = dob;
    }
    public String getDob(){
        return this.dob;
    }
    public void setRefNo(String refNo){
        this.refNo = refNo;
    }
    public String getRefNo(){
        return this.refNo;
    }
    public void setResult(String result){
        this.result = result;
    }
    public String getResult(){
        return this.result;
    }
}

  public class Root
   {
    private String applicationType;

    private ResponseMessage responseMessage;

    public void setApplicationType(String applicationType){
        this.applicationType = applicationType;
    }
    public String getApplicationType(){
        return this.applicationType;
    }
    public void setResponseMessage(ResponseMessage responseMessage){
        this.responseMessage = responseMessage;
    }
    public ResponseMessage getResponseMessage(){
        return this.responseMessage;
    }
 }

now final code(최종코드)

 if(responseMessage.getSurname() !=null){
  ---do something---
 }
 if(responseMessage.getForename !=null){
   ----do something
 }
 if(responseMessage.getDob() !=null){
  ---do something---
 }
 if(responseMessage.getRefNo() !=null){
   ---do something---
 }
 if(responseMessage.getResult() !=null){
   ---do something---
 }

언급URL : https://stackoverflow.com/questions/24279245/how-to-handle-dynamic-json-in-retrofit

반응형