Для провайдера этого интерфейса самый внешнийresultcodereasonиresultВсе три элемента присутствуют. Таким образом, мы можем определить такойResponseсвоего рода
public class Response<T> {
private String resultcode;
private String reason;
private T result;
}
Используйте дженерики, чтобы решить, чем в конечном итоге будет заполнен результат. Конечно, то, что здесь заполнено, является объектом, и мы также можем определить его какUserсвоего рода
public class User {
private String area;
private String sex;
private String birthday;
}
Таким образом, наши данные могут быть возвращены вызывающей стороне в соответствии с правилами соглашения примера json.
В качестве вызывающей стороны, то есть машины, которая получает эти данные, нам нужно определить следующий классResopnseUser
public class ResopnseUser {
private String resultcode;
private String reason;
private User result;
}
public class User {
private String area;
private String sex;
private String birthday;
}
Затем мы можем использовать fastJson для удачного синтаксического анализа.
Однако это имеет менее серьезные последствия. Каждый раз, когда я подключаю интерфейс к провайдеру, мне приходится генерировать соответствующий класс. Со временем эти специализированные классы будут становиться все более и более глубоко вложенными. Поскольку провайдер может абстрагироватьResponseclass, так я могу сделать это и с провайдером?
К сожалению, результаты, которые мы получили, оказались не такими, как мы ожидали, удался только внешний парсинг данных, а внутреннийresultвсе ещеJSONObject.
форум для помощи
К счастью, это решение не единственное среди тысяч инженеров, уже решивших подобного рода задачи!
С помощью различных поисков мы обнаружили, что fastJson предоставляетTypeReferenceЭтот класс может решить нашу проблему.
Очень хорошо, мы получили желаемый результат, и, наконец, мы можем унифицировать оценку самого внешнего возвращаемого значения всех интерфейсов.
никогда не останавливайся здесь
И так далее, вопросов ко мне не нашлось? Обобщения во время выполнения компиляциистирание типаКакие! Это также первый раз, когда мы напрямую используемResponse<User> response = JSONObject.parseObject(testJson,Response.class);Неверная причина.
Ну, даже если мы напишемnew TypeReference<Response<User>>(){}Его тоже не стереть? Как он переходит к фактическому типу, который мы определили во время выполнения?
просмотревTypeReferenceК счастью, исходный код очень прост, а объем кода невелик. Первое, что нужно ввести, это его конструкторprotected TypeReference(), путем отладки мы обнаружили, что написанный нами универсальный тип был получен при выполнении кода до второй строки.
Type superClass = getClass().getGenericSuperclass();
Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
Этот код очень прост, перейдите к его родительскому классуgetGenericSuperclass()Фактический тип получен, продолжая следить за кодом, мы можем обнаружить, что он вызывает нативный методprivate native String getGenericSignature0();Получить некоторую информацию о классе и родительском классеClassRepositoryиType.
В этот момент давайте оглянемся назадnew TypeReference<Response<User>>(){}На самом деле создалTypeReferenceАнонимный внутренний класс класса черезgetGenericSuperclass()Получите информацию о фактической информации.
продолжать копать
Давайте теперь рассмотрим, что у нас получилось, и отметим 2 момента:
Дженерики выполняются во время компиляциистирание типа.
получить его родительский классgetGenericSuperclass()Чтобы добраться до фактического типа.
И т.д., эти два взаимно противоречат ах. 1 сказал нет, два сказали найду, в итоге как получилось? Просмотрев файлы, скомпилированные с помощью байт-кода, мы нашли ответ.Вот код, который содержитResponse<User> response = JSONObject.parseObject(testJson,new TypeReference<Response<User>>(){});Декомпилированная информация файла класса метода. Мы видим, что
у него есть еще одинLocalvariableTypeTable,внутриSignatureСохраняется только фактическая информация о типе. **То есть тип не стирается полностью, и мы все еще можем получить тип параметра через отражение. ** Так называемое стирание, просто поставьте методcodeБайт-код атрибута стирается.
Кроме того, мы также виделиInnerClassesВ списке есть внутренний класс Main$1, который принадлежит нам.new TypeReference<Response<User>>(){}
Суммировать
в состоянии пройтиJSONObject.parseObject(testJson,new TypeReference<Response<User>>(){});способ решить проблему вложенных дженериков в json. Удобно, быстро и интуитивно понятно
в состоянии пройтиgetClass().getGenericSuperclass();Получите настоящий тип. код верификации
// 这类创建了一个HashMap的匿名子类
HashMap<String,Integer> subIntMap = new HashMap<String,Integer>(){};
System.out.println(subIntMap.getClass().getSuperclass());
Type subClassType = subIntMap.getClass().getGenericSuperclass();
if(subClassType instanceof ParameterizedType){
ParameterizedType p = (ParameterizedType) subClassType;
for (Type t : p.getActualTypeArguments()){
System.out.println(t);
}
}
выходной результат
class java.util.HashMap
class java.lang.String
class java.lang.Integer
Тип полностью не стирается, а тип параметра можно получить путем отражения. код верификации
ResponseUser response = new ResponseUser();
Field field = response.getClass().getField("result");
System.out.println("result Type is "+ field.getType());
System.out.println("result GenericType is "+ field.getGenericType());
public class ResponseUser {
private String resultcode;
private String reason;
public List<User> result;
}
выходной результат
result Type is interface java.util.List
result GenericType is java.util.List<com.jd.jr.alpha.cpa.fastJson.User>