[ Gson Serialize ]필드는 늘이 아니거나 공백이 아닌 경우에만
java 객체를 json으로 변환해야 하는 요건이 있습니다.
Gson을 사용하고 있는데 null이 아닌 값이나 비어 있지 않은 값만 시리얼화하려면 변환기가 필요합니다.
예를 들어 다음과 같습니다.
//my java object looks like
class TestObject{
String test1;
String test2;
OtherObject otherObject = new OtherObject();
}
이 개체를 json으로 변환하는 Gson 인스턴스는 다음과 같습니다.
Gson gson = new Gson();
TestObject obj = new TestObject();
obj.test1 = "test1";
obj.test2 = "";
String jsonStr = gson.toJson(obj);
println jsonStr;
위의 인쇄에서 결과는 다음과 같습니다.
{"test1":"test1", "test2":"", "otherObject":{}}
여기서 난 그저 결과가 좋기를 바랐다.
{"test1":"test1"}
test2가 비어 있고 otherObject가 비어 있기 때문에 json 데이터로 시리얼화하지 않았으면 합니다.
참고로 저는 Groovy/Grails를 사용하고 있기 때문에 이 플러그인이 있다면 gson serialization class를 커스터마이즈하는 것이 좋을 것 같습니다.
독자적인 작성TypeAdapter
public class MyTypeAdapter extends TypeAdapter<TestObject>() {
@Override
public void write(JsonWriter out, TestObject value) throws IOException {
out.beginObject();
if (!Strings.isNullOrEmpty(value.test1)) {
out.name("test1");
out.value(value.test1);
}
if (!Strings.isNullOrEmpty(value.test2)) {
out.name("test2");
out.value(value.test1);
}
/* similar check for otherObject */
out.endObject();
}
@Override
public TestObject read(JsonReader in) throws IOException {
// do something similar, but the other way around
}
}
그런 다음 에 등록할 수 있습니다.Gson
.
Gson gson = new GsonBuilder().registerTypeAdapter(TestObject.class, new MyTypeAdapter()).create();
TestObject obj = new TestObject();
obj.test1 = "test1";
obj.test2 = "";
System.out.println(gson.toJson(obj));
생산하다
{"test1":"test1"}
그GsonBuilder
클래스에는 독자적인 시리얼화/디시리얼화 스트래티지 작성, 타입 어댑터 등록 및 기타 파라미터 설정을 위한 다양한 메서드가 있습니다.
Strings
과바 클래스입니다.그런 종속성을 원하지 않으면 직접 확인할 수 있습니다.
제가 개인적으로 싫어하는 건TypeAdapter
50개의 필드(50개의 필드, 즉 50개의 필드)를 가질 수 있는 전체 클래스의 모든 필드를 설명할 필요가 있다는 사실을 사용합니다.if
블록 인TypeAdapter
).
저의 솔루션은Reflection
그리고 사실Gson
는 디폴트로는 늘 값 필드를 시리얼화하지 않습니다.
DocumentModel이라고 하는 API용 데이터를 보관하고 있는 특별한 클래스가 있습니다.이 클래스는 50개 정도의 필드가 있으며 전송은 좋아하지 않습니다.String
" (비어 있지만 null이 아님) 값이 있는 필드 또는 빈 배열이 서버에 표시됩니다.그래서 빈 필드를 모두 무효로 하고 오브젝트의 복사본을 반환하는 특별한 메서드를 만들었습니다.주의 - 기본적으로는 DocumentModel 인스턴스의 모든 어레이는 빈 (0길이) 어레이로 초기화되므로 늘이 아닙니다.아마도 길이를 체크하기 전에 어레이의 늘을 확인해야 합니다.
public DocumentModel getSerializableCopy() {
Field fields[] = new Field[]{};
try {
// returns the array of Field objects representing the public fields
fields = DocumentModel.class.getDeclaredFields();
} catch (Exception e) {
e.printStackTrace();
}
DocumentModel copy = new DocumentModel();
Object value;
for (Field field : fields) {
try {
value = field.get(this);
if (value instanceof String && TextUtils.isEmpty((String) value)) {
field.set(copy, null);
// note: here array is not being checked for null!
else if (value instanceof Object[] && ((Object[]) value).length == 0) {
field.set(copy, null);
} else
field.set(copy, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return copy;
}
이 방법을 사용하면 이 방법을 쓴 후 일부 필드가 추가 또는 제거되었든 상관 없습니다.남은 유일한 문제는 커스텀타입 필드를 체크하는 것입니다.이 필드는 체크되지 않습니다.String
또는 배열이지만 이는 특정 클래스에 따라 다르며 if/clocks에서 추가 코딩해야 합니다.
내가 보기에 문제는 gson이 아닌 것 같다.Gson은 null 문자열과 빈 문자열의 차이를 올바르게 추적합니다.이 구별을 지우시겠습니까?TestObject를 사용하는 모든 클래스가 상관없습니다.
차이를 신경 쓰지 않는 경우 TestObject 내에서 빈 문자열을 null로 변경한 후 시리얼화합니다.또는 빈 문자열이 null로 설정되도록 TestObject의 setters를 만듭니다.그러면 빈 문자열이 null과 동일하도록 클래스 내에서 엄격하게 정의할 수 있습니다.설정기 밖에서 값을 설정할 수 없는지 확인해야 합니다.
같은 문제에 부딪혀 두 가지 다른 해결책을 찾았습니다.
- 각 필드 클래스에 대해 사용자 지정 유형 어댑터 작성
String 클래스의 TypeAdapter 예제:
@SuppressWarnings("rawtypes")
public class JSONStringAdapter extends TypeAdapter {
@Override
public String read(JsonReader jsonReader) throws IOException {
String value = jsonReader.nextString();
if(value == null || value.trim().length() == 0) {
return null;
} else {
return value;
}
}
@Override
public void write(JsonWriter jsonWriter, Object object) throws IOException {
String value = String.valueOf(object);
if(value == null || value.trim().length() == 0) {
jsonWriter.nullValue();
} else {
jsonWriter.value(value);
}
}
}
용도:
public class Doggo {
@JsonAdapter(JSONStringAdapter.class)
private String name;
public Doggo(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
Doggo aDoggo = new Doggo("");
String jsonString = new Gson().toJson(aDoggo);
}
}
- JSON 문자열을 생성하기 전에 개체를 수동으로 처리합니다.
동작하고 있는 것 같으며, 퍼포먼스를 테스트하지 않았습니다.
public static boolean removeEmpty(JSONObject source) {
if (null == source || source.length() == 0) {
return true;
}
boolean isJsonObjectEmpty = false;
for (String key : JSONObject.getNames(source)) {
Object value = source.get(key);
boolean isValueEmpty = isValueEmpty(value);
if(isValueEmpty) {
source.remove(key);
}
}
if(source.length() == 0) {
isJsonObjectEmpty = true;
}
return isJsonObjectEmpty;
}
private static boolean isValueEmpty(Object value) {
if (null == value) {
return true;
}
if (value instanceof JSONArray) {
JSONArray arr = (JSONArray) value;
if(arr.length() > 0) {
List<Integer> indextesToRemove = new ArrayList<>();
for(int i = 0; i< arr.length(); i++) {
boolean isValueEmpty = isValueEmpty(arr.get(i));
if(isValueEmpty) {
indextesToRemove.add(i);
};
}
for(Integer index : indextesToRemove) {
arr.remove(index);
}
if(arr.length() == 0) {
return true;
}
} else {
return true;
}
} else if (value instanceof JSONObject) {
return removeEmpty((JSONObject) value);
} else {
if (JSONObject.NULL.equals(value)
|| null == value
|| value.toString().trim().length() == 0)
) {
return true;
}
}
return false;
}
용도:
public class Doggo {
private String name;
public Doggo(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
Doggo aDoggo = new Doggo("");
// if you are not using Type Adapters for your fields
JSONObject aJSONObject1 = new JSONObject(aDoggo);
removeEmpty(aJSONObject1);
String jsonString1 = aJSONObject1.toString();
// if you are using Type Adapters for your fields
Gson gsonParser = new Gson();
JSONObject aJSONObject2 = new JSONObject(gsonParser .toJson(aDoggo));
removeEmpty(aJSONObject2);
String jsonString2 = aJSONObject2.toString();
}
}
언급URL : https://stackoverflow.com/questions/18491733/gson-serialize-field-only-if-not-null-or-not-empty
'programing' 카테고리의 다른 글
단위 테스트 약속 기반 코드(Angularjs) (0) | 2023.04.02 |
---|---|
FormController에서 양식 제어 가져오기 (0) | 2023.04.02 |
Wordpress 역할 표시 이름 (0) | 2023.04.02 |
스프링 부트 애플리케이션을 올바른 방법으로 셧다운하려면 어떻게 해야 합니까? (0) | 2023.04.02 |
Wordpress의 사용자 지정 분류법에서 모든 게시물 가져오기 (0) | 2023.04.02 |