Gson 문자열 null 필드 를 빈 문자열 로 변환 합 니 다.
4551 단어 기술 소 해
엄밀 한 프로그래머 에 게 는 참 을 수 없다.그래서 더 완벽 한 방법 을 찾 고 싶 었 다.
먼저 인터넷 에 현재 존재 하 는 두 가지 방법 을 말 해 보 자.
1. NullStringToEmpty Adapter Factory 를 쓰 고 new Gson Builder (). registerTypeAdapter Factory (new NullStringToEmpty Adapter Factory () 를 사용 합 니 다.
2. new TypeAdapter 내부 클래스 를 사용 한 다음 new GsonBuilder (). registerTypeAdapter (String. class, STRING) 를 사용 합 니 다.
그리고 나 서 나 는 모두 시험 해 보 았 지만 방법 하 나 는 전혀 효과 가 없 었 고 방법 하 나 는 잘못 을 갚 았 다.
만약 당신 이 위의 두 가지 중 어느 한 가지 방법 이 모두 성공 했다 면, 축하합니다. 직접 소스 분석 단계 에 들 어 갈 수 있 습 니 다.
만약 당신 이 불행 하 게 도 나 와 같다 면, 여전히 안 된다 면, 나 는 당신 이 나 와 마찬가지 로, gs on jar 가방 문 제 를 만 날 수 있 을 것 이 라 고 생각 합 니 다!문제 가 있 는 것 은 gson - 2.2.1. jar 버 전이 다.
소스 코드 를 연구 해 보 니 위의 두 가지 방법 이 모두 안 되 는 원인 을 찾 았 다.
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter)
{
Gson.Preconditions.checkArgument(((typeAdapter instanceof JsonSerializer)) || ((typeAdapter instanceof JsonDeserializer)) || ((typeAdapter instanceof InstanceCreator)) || ((typeAdapter instanceof TypeAdapter)));
if ((Primitives.isPrimitive(type)) || (Primitives.isWrapperType(type)) || (type == String.class)) {
throw new IllegalArgumentException("Cannot register type adapters for " + type);
}
if ((typeAdapter instanceof InstanceCreator)) {
this.instanceCreators.put(type, (InstanceCreator)typeAdapter);
}
if (((typeAdapter instanceof JsonSerializer)) || ((typeAdapter instanceof JsonDeserializer))) {
TypeToken typeToken = TypeToken.get(type);
this.factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));
}
if ((typeAdapter instanceof TypeAdapter)) {
this.factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));
}
return this;
}
방법 2 보 오 류 는 원본 코드 가 사용자 가 기본 형식 과 패 키 징 형식 을 사용자 정의 할 수 없 기 때 문 입 니 다.방법 1. adapter 공장 에 등 록 했 지만 구 글 은 사용자 정의 adapter 를 사용 하지 않 았 다.
if (!Primitives.isPrimitive(type) && !Primitives.isWrapperType(type) && type != String.class)
{
}
else
{
throw new IllegalArgumentException("Cannot register type adapters for " + type);
}
gson - 2.2.2 이후 버 전 에는 위의 코드 가 없어 서 사용자 정의 adapter 를 등록 할 수 있 습 니 다.
나 는 gson 버 전 을 업 그 레이 드 했 고 gson - 2.5 를 사 용 했 지만 빈 문자열 을 출력 하지 않 았 다. 그래서 나 는 다시 원본 코드 를 보 러 갔다.
처음에 나 는 어떤 글 을 참고 하여 publicvoidwrite (JSonWriterwriter, Stringvalue) 에 다음 과 같은 코드 를 썼 다.
if (value == null)
{
writer.nullValue();
return;
}
그게 문제 야.
직렬 화 는 adapter 의 write 방법 을 사용 하고 반 직렬 화 는 read 방법 을 사용 하기 때문에 write 방법 에 써 야 합 니 다.
if (value == null)
{
writer.value("");
return;
}
마침내 문 제 를 해결 했다.
이제 null 필드 를 빈 문자열 로 출력 하 는 방법 을 완벽 하 게 해결 하 는 방법 을 정리 합 니 다.정적 adapter 상수 만 정의 하고 Gson Builder 에 등록 하면 됩 니 다.인터넷 에서 NullStringToEmpty Adapter Factory 와 StringNullAdapter 류 를 정의 하 는 것 은 필요 하지 않 습 니 다.
왜?원본 코드 에 적 혀 있 습 니 다. 사용자 정의 adapter 를 사용 하면 gs on 은 adapter Factory 로 재 구성 하여 등록 합 니 다.
if(typeAdapter instanceof TypeAdapter)
{
this.factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));
}
마지막 으로 최종 코드 샘플 을 드 리 겠 습 니 다.
public class TestMain
{
// Strig
private static final TypeAdapter STRING = new TypeAdapter()
{
public String read(JsonReader reader) throws IOException
{
if (reader.peek() == JsonToken.NULL)
{
reader.nextNull();
return "";
}
return reader.nextString();
}
public void write(JsonWriter writer, String value) throws IOException
{
if (value == null)
{
// null
writer.value("");
return;
}
writer.value(value);
}
};
public static void main(String[] args)
{
GsonBuilder gsonBuilder = new GsonBuilder();
// String
gsonBuilder.registerTypeAdapter(String.class, STRING);
Gson gson = gsonBuilder.create();
UserBean userBean = new UserBean();
userBean.setId("1");
System.out.println(gson.toJson(userBean));
}
}