Json Deserializer - Gson 사용자 정의 해석 형식 오류 필드
16363 단어 Android
그러나 가끔 은 배경 에서 클 라 이언 트 에 게 전 달 된 json 데이터 형식 이 잘못 되 었 습 니 다. 그 중의 일부 필드 형식 이 잘못 되 었 습 니 다. 즉, 우리 가 실체 류 에서 정의 한 필드 형식 과 일치 하지 않 으 면 유형 변환 오류 가 발생 하고 app 이 제자리 에서 폭발 합 니 다!
만약 에 이런 종류
Phone
가 핸드폰 을 대표 한다 고 가정 하면/**
* Author: Sbingo
* Date: 2017/4/23
*/
public class Phone {
/**
*
*/
private Size size;
/**
* app
*/
private List apps;
public Size getSize() {
return size;
}
public void setSize(Size size) {
this.size = size;
}
public List getApps() {
return apps;
}
public void setApps(List apps) {
this.apps = apps;
}
}
그 중에서 유형
Size
은 다음 과 같다./**
* Author: Sbingo
* Date: 2017/4/23
*/
class Size {
private String length;
private String width;
private String height;
public String getLength() {
return length;
}
public void setLength(String length) {
this.length = length;
}
public String getWidth() {
return width;
}
public void setWidth(String width) {
this.width = width;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
}
클래스
App
는 다음 과 같다./**
* Author: Sbingo
* Date: 2017/4/23
*/
class App {
private String appName;
private String developer;
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getDeveloper() {
return developer;
}
public void setDeveloper(String developer) {
this.developer = developer;
}
}
클래스
Phone
에 대해 실제 내 가 만난 데이터 형식 오류 상황 은 다음 과 같다.대상 size 가 문자열 로 바 뀌 었 습 니 다.
배열 apps 가 문자열 로 바 뀌 었 습 니 다.
다음은 이 두 가지 잘못 에 대해 각각 토론 할 것 이 며, 다른 잘못 은 유사 하 게 처리 할 수 있다.
물론 이 문자열 은 전의 문 자 를 가 진 json 문자열 입 니까? 아니면 정확 한 정 보 를 포함 하고 있 습 니까?따라서 다음 문자열 에 대한 처 리 는 이러한 오류 에 만 적 응 될 수 있 습 니 다.
어떻게 이 문 제 를 해결 합 니까?
가장 좋 은 방법 은 당연히 백 스테이지 에서 데이터 형식 이 정확 하고 원천 적 으로 문 제 를 없 애 는 것 이다.
클 라 이언 트 개발 로 서 우 리 는 잘못된 처 리 를 하고 각종 장면 에 대응 해 야 한다.
클 라 이언 트 는 어떻게 처리 합 니까?
registerTypeAdapter
사실 Gson 은 특정한 유형의 데 이 터 를 사용자 정의 로 해석 할 수 있 습 니 다. 보통 Gson 을 사용 하면 new 로 나 올 수 있 습 니 다. 그러나 이렇게 예화 하면:
Gson gson = new GsonBuilder()
.registerTypeAdapter(A.class, new ADeserializer())
.registerTypeAdapter(B.class, new BDeserializer())
.create()
받 은 gson 은 사용자 정의
ADeserializer
와 BDeserializer
를 각각 반 서열 화 클래스 A 와 클래스 B 로 사용 합 니 다.` registerTypeAdapter 방법 은 Gson 의 직렬 화 또는 반 직렬 화 를 설정 하고 두 개의 인 자 를 받 는 데 사 용 됩 니 다.
첫 번 째 매개 변 수 는 등 록 된 형식 입 니 다. 즉, 사용자 정의 로 해석 하고 자 하 는 데이터 형식 입 니 다.
두 번 째 매개 변 수 는 사용자 정의 분석 과정 을 포함 하 는데 적어도
TypeAdapter
, InstanceCreator
, JsonSerializer
, JsonDeserializer
네 가지 중 하나 가 실현 되 어야 합 니 다.JsonDeserializer
범 형 인터페이스
JsonDeserializer
의 방법 deserialize
은 우리 가 반 직렬 화 과정 을 사용자 정의 하여 해당 하 는 대상 으로 돌아 갈 수 있 도록 합 니 다.이 방법 은 세 개의 인 자 를 받 아들 이 고 Gson 은 해당 유형의 필드 의 역 직렬 화 를 진행 할 때 이 방법 을 되 돌려 줍 니 다.
첫 번 째 매개 변수 유형 은 JSonElement 인 데 그 중에서 실제 되 돌아 온 데 이 터 를 포함 하고 추상 적 인 유형 으로
JsonObject
, JsonArray
, JsonPrimitive
, JsonNull
네 가지 중 하나 로 이름 을 봐 도 이 네 가지 대체적인 유형 을 알 수 있다.두 번 째 매개 변 수 는 현재 반 직렬 화 된 데이터 형식 입 니 다.
세 번 째 는 문맥 파라미터
context
입 니 다.사용자 정의 반 직렬 화 를 할 때 저 희 는 데이터 형식 이 정확 하고 잘못된 상황 을 각각 처리 하고 구체 적 인 처리 과정 은 데이터 에 따라 정 하 며 다음은 참고 하 시기 바 랍 니 다.
오류 1: 대상 size 가 문자열 로 바 뀌 었 습 니 다.
필드 size 는 Size 대상 형식 입 니 다. 배경 인터페이스 가 문자열 을 되 돌려 줄 때 Size 형식 에 대해 서 만 반 직렬 화 할 수 있 습 니 다. 다음 과 같 습 니 다.
/**
* Author: Sbingo
* Date: 2017/4/23
*/
public class SizeDeserializer implements JsonDeserializer<Size> {
@Override
public Size deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Size size = new Size();
if (json.isJsonObject()) {
//
JsonObject jsonObject = json.getAsJsonObject();
size.setLength(jsonObject.get("length").getAsString());
size.setWidth(jsonObject.get("width").getAsString());
size.setHeight(jsonObject.get("height") == null ? "" : jsonObject.get("height").getAsString());
} else {
//
String value = json.getAsString();
size = new Gson().fromJson(value, Size.class);
}
return size;
}
}
일반적인 매개 변 수 는 Size 에 들 어 갑 니 다. 반 직렬 화 Size 대상 이 있 을 때 사용자 정의 방법 을 되 돌려 줍 니 다.
우선
isJsonObject()
으로 대상 여 부 를 판단 한다.만약 그렇다면, 설명 유형 이 정확 하고, 이어서 각 필드 값 을 순서대로 설정 합 니 다.만약 일부 필드 인터페이스 가 되 돌아 오지 않 을 수도 있 으 니, 예 를 들 어 필드
height
를 비 워 두 는 것 을 기억 하 세 요.형식 이 잘못 되면 제 가 만난 오 류 는 전의 문자 가 있 는 문자열 일 뿐 이 므 로 이 를 누 르 십시오.호출
json.getAsString()
하면 정확 한 json 문자열 을 얻 을 수 있 고 Gson 을 통 해 Size 형식 으로 직접 변환 할 수 있 습 니 다.이렇게 하면 인터페이스 가 데이터 의 필드
size
유형 이 정확 하 든 안 하 든 여 유 롭 게 대응 할 수 있 습 니 다!오류 2: 배열 apps 가 문자열 로 바 뀌 었 습 니 다.
필드 apps 는 list 입 니 다. 인 터 페 이 스 는 하나의 배열 로 돌아 가 야 합 니 다. 만약 유형 이 잘못 되면 두 가지 방식 으로 사용자 정의 해석 을 할 수 있 습 니 다. 제 가 보기 에는 이 두 가지 가 각각 우열 이 있 고 구체 적 으로 사용 하려 면 실제 와 결합 해 야 합 니 다.
사용자 정의 해석 필드 자체
이런 방법 은 해석
size
과 유사 하 며 '유형 이 틀 리 면 해석 하 라' 는 원칙 에 따른다.List
을 일반적인 매개 변수 로 사용 하 는 방법 을 찾 지 못 했 기 때문에 클래스 Phone
의 필드 apps
를 list 에서 배열 로 바 꿔 야 합 니 다. 만약 에 배열 로 만 바 꿀 수 있다 면 사용 편의 성 이 list 보다 약간 떨 어 질 수 있 습 니 다.정의
AppDeserializer
는 다음 과 같다./**
* Author: Sbingo
* Date: 2017/4/23
*/
public class AppDeserializer implements JsonDeserializer {
@Override
public App[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonArray()) {
//
JsonArray jsonArray = json.getAsJsonArray();
App[] apps = new App[jsonArray.size()];
for (int i = 0; i < jsonArray.size(); i++) {
App app = new App();
// app
JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
app.setAppName(jsonObject.get("appName") == null ? "" : jsonObject.get("appName").getAsString());
app.setDeveloper(jsonObject.get("developer") == null ? "" : jsonObject.get("developer").getAsString());
// app
// app = context.deserialize(jsonObject, App.class);
apps[i] = app;
}
return apps;
} else if (json.isJsonObject()) {
// 1
return null;
} else if (json.isJsonPrimitive()) {
// 2, String
String value = "";
try {
value = json.getAsString();
} catch (Exception e) {
e.printStackTrace();
}
if ("".equals(value)) {
return null;
} else {
App[] apps = new Gson().fromJson(value, App[].class);
return apps;
}
} else {
//
return null;
}
}
}
범 형 매개 변 수 는 배열 에 전 달 됩 니 다. 반 직렬 화 된 App 형식의 배열 이 있 을 때 사용자 정의 방법 을 되 돌려 줍 니 다.
먼저
isJsonArray()
유형 이 정확 한 지, 정확 할 때 배열 을 얻 는 방법 도 두 가지 가 있 습 니 다. 코드 와 같이...방법 은 이전의 분석 과 차이 가 많 지 않다.
방법 2 주의
context
반 직렬 화 시 사순환 에 들 어가 지 않도록 해 야 한다.유형 이 틀 렸 을 때 비교적 많은 구분 을 했 으 니 구체 적 으로 는 실제 상황 을 보아 야 한다.
사용자 정의 해석 필드 소재 클래스
이 방법 은 오류 필드 apps 가 있 는 클래스 Phone 을 처리 유형 으로 합 니 다. 필드 apps 는 list 를 사용 할 수 있 지만 클래스 에 다른 필드 가 많 으 면 작업량 이 많 습 니 다. 다행히 여 기 는 size 만 있 습 니 다.
정의
AppListDeserializer
는 다음 과 같다./**
* Author: Sbingo
* Date: 2017/4/23
*/
public class AppListDeserializer implements JsonDeserializer<Phone> {
@Override
public Phone deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Phone phone = new Phone();
JsonObject jsonObject = json.getAsJsonObject();
// size
if (jsonObject.get("size") != null) {
jsonObject = jsonObject.get("size").getAsJsonObject();
Size size = context.deserialize(jsonObject, Size.class);
phone.setSize(size);
}
JsonElement appsArray = jsonObject.get("apps");
if (appsArray != null) {
List apps = new ArrayList<>();
if (appsArray.isJsonArray()) {
//
JsonArray jsonArray = appsArray.getAsJsonArray();
for (int i = 0; i < jsonArray.size(); i++) {
JsonObject jo = jsonArray.get(i).getAsJsonObject();
App app = context.deserialize(jo, App.class);
apps.add(app);
}
} else {
//
String value = appsArray.getAsString();
App[] a = new Gson().fromJson(value, App[].class);
apps = Arrays.asList(a);
}
phone.setApps(apps);
}
return phone;
}
}
일반적인 매개 변 수 는 Phone 에 전 송 됩 니 다. Phone 형식 데 이 터 를 역 직렬 화 할 때 사용자 정의 방법 을 되 돌려 줍 니 다.
필드
apps
를 처리 하기 때문에 필드 size
의 유형 이 정확 한 지 여 부 를 고려 하지 않 습 니 다.Phone 은 대상 이 확실 하기 때문에
getAsJsonObject()
방법 으로 하나 JsonObject
를 직접 얻 을 수 있 습 니 다.그 다음 에 필드
size
와 apps
를 각각 설정 하 는데 그 중에서 사용 하 는 방법 은 위 와 유사 하 다.Json Deserializer 사용자 정의 반 직렬 화 사고방식 은 대체로 이렇다. 앞으로 유사 한 오 류 를 처리 하 는 것 은 666 이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.