1

Here is My Json Result Code:

      {
    "head": {
      "rspCode": 0,
      "rspMsg": "成功",
      "dataVersion": "",
      "appVersion": "",
      "deployVersion": "",
      "msgCount": ""
    },
    "body": {
      "orderNo": 166,
      "orderTime": "2017-07-27 09:30:48",
      "orderStatus": "Pending",
      "productsPart": [
        {
          "name": "iPhone",
          "total": 101,
          "orderProtList": [
            {
              "productSkuPrice": "101.0000",
              "productQuantity": "1",
              "productSku": "quantity"
            }
          ]
        }
      ]
    }
    }

Here is My Entity Code,i am useing retrofit to rebuild my code structure ,but convert the json stumped me:

public class ResponseObj<T> {
private RespHeader head;
private T body;
........
(get set methods ignored)
}

RespHead.java:

public class RespHeader {
private String dataVersion;
private String appVersion;
private String deployVersion;
private String msgCount;
private int rspCode; //响应码
private String rspMsg;
.....
  (get set methods ignored)
 }

Here is the Body Class Content :

private int orderNo;
private String orderTime;
private String orderStatus;
private List<ProductsPartBean> productsPart;
...... 
(get set ignored)

I tried to use define custom GsonConverter to convert this JSON text. Here are my steps:

public class GsonResponseConverter extends Converter.Factory {
private Gson gson;

public GsonResponseConverter(Gson gson) {
    this.gson = gson;
}


public static GsonResponseConverter create() {
    return create(new Gson());
}

@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static GsonResponseConverter create(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    return new GsonResponseConverter(gson);
}


@Nullable
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = this.gson.getAdapter(TypeToken.get(type));
    return new CustomResponseConverter<>(this.gson);
}

@Nullable
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
}

@Nullable
@Override
public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
    return super.stringConverter(type, annotations, retrofit);
}

private static class CustomResponseConverter<T> implements Converter<ResponseBody, ResponseObj<T>> {
    Gson gson;
    public CustomResponseConverter(Gson gson) {
        this.gson = gson;
    }
    @Override
    public ResponseObj<T> convert(ResponseBody value) throws IOException {
        String valueString = value.string();
        JSONObject obj = null;
        ResponseObj<T> resp = new ResponseObj();
        try {
            obj = new JSONObject(valueString);
            if (obj.has("head")) {
                JSONObject obj_head = obj.getJSONObject("head");
                resp.setHead(gson.fromJson(obj_head.toString(), RespHeader.class));
            }
            if (obj.has("body")) {
                JSONObject obj_body = obj.optJSONObject("body");
                if (!InputHelper.isEmpty(obj_body) && obj_body.length() > 0) {
                    resp.setBody(gson.fromJson(obj_body.toString(), (Type) resp.getBody().getClass()));
                } else {
                    resp.setBody(null);
                }
            }
        } catch (JSONException e) {
            Logger.e(e.getMessage());
            RespHeader header = new RespHeader();
            header.setRspCode(001);
            header.setRspMsg("server response error");
            resp.setHead(header);
            resp.setBody(null);
        }
        return resp;
    }
}
 }

my generic did not work because I Init a null ResponseObj that my body generic did not incoming, how can I do to resolve this question, what's the correct way to use it?

Smish jack
  • 84
  • 11

2 Answers2

0

Looking here...

resp.setBody(gson.fromJson(obj_body.toString(), (Type) resp.getBody().getClass()));

You're calling a getter and setter on the same line. The getter will always return null unless previously set (which it doesn't look like it is).

My suggestion would be something like so

public class ResponseObj<T> {
    private RespHeader head;
    private T body;

    public Type getType() {
        // TODO
    }
}

With resp.getType() not relying on the Body (because the Object content/reference is a separate variable than the Class that represents it)

Worth mentioning: You can't get the class of a generic ... How to get a class instance of generics type T

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • thx for your answer, My Generic doesn't work, so I temporarily change the Entity to parse JSON Data, I will try this way in another time. – Smish jack Aug 29 '17 at 00:42
0

1) You can use Gson Converter for Retrofit 2

2) Then create POJO objects. You can use this tool . Check Source type: JSON and Annotation style: Gson

3) Create your requests using Retrofit 2 and use your POJO objects for response from server.

4) Profit!

eltray
  • 365
  • 4
  • 9
  • thx for your answer, I was tried use Generic to build a common JSON converter, I used to do this before, I'm trying some new way to parse JSON Data – Smish jack Aug 29 '17 at 00:40
  • If you compare the code in the question with that link, you'll see the question actually modified the very same. – OneCricketeer Aug 29 '17 at 01:28