Gson : 주석없이 직렬화에서 특정 필드를 제외하는 방법


413

나는 Gson을 배우려고 노력하고 있으며 필드 배제로 고심하고 있습니다. 여기 내 수업이 있습니다

public class Student {    
  private Long                id;
  private String              firstName        = "Philip";
  private String              middleName       = "J.";
  private String              initials         = "P.F";
  private String              lastName         = "Fry";
  private Country             country;
  private Country             countryOfBirth;
}

public class Country {    
  private Long                id;
  private String              name;
  private Object              other;
}

GsonBuilder를 사용하고 firstName또는 같은 필드 이름에 ExclusionStrategy를 추가 할 수는 있지만와 같은 country특정 필드의 속성을 제외시키는 것은 관리 할 수 ​​없습니다 country.name.

이 메소드를 사용하면 public boolean shouldSkipField(FieldAttributes fa)FieldAttributes에 필터와 같은 필드를 일치시키기에 충분한 정보가 없습니다 country.name.

추신 : 나는 이것을 개선하고 RegEx를 사용하여 필드를 필터링하기 때문에 주석을 피하고 싶습니다.

편집 : Struts2 JSON 플러그인 의 동작을 에뮬레이트 할 수 있는지 확인하려고합니다.

Gson 사용

<interceptor-ref name="json">
  <param name="enableSMD">true</param>
  <param name="excludeProperties">
    login.password,
    studentList.*\.sin
  </param>
</interceptor-ref>

편집 : 다음을 추가하여 질문을 다시 열었습니다.

이 문제를 더 명확히하기 위해 동일한 유형의 두 번째 필드를 추가했습니다. 기본적으로 제외하고 싶지는 country.name않습니다 countrOfBirth.name. 또한 국가를 유형으로 제외하고 싶지 않습니다. 따라서 유형은 객체 그래프에서 정확히 지적하고 제외하려는 실제 위치와 동일합니다.


1
여전히 2.2 버전부터는 제외 할 필드의 경로를 지정할 수 없습니다. flexjson.sourceforge.net 은 좋은 대안처럼 느껴집니다.
— Liviu T.

비슷한 질문에 대한 대답 을 살펴보십시오 . 직렬화 할 필드를 결정하는 적용되는 JsonSerializer일부 유형에 대한 사용자 정의 작성을 기반으로 Country합니다 ExclusionStrategy.
— pirho

답변:


625

일반적으로 직렬화하지 않으려는 모든 필드는 "일시적"수정자를 사용해야하며 이는 json 직렬화 기에도 적용됩니다 (적어도 gson을 포함하여 내가 사용한 몇 가지에 해당).

직렬화 된 json에 이름을 표시하지 않으려면 임시 키워드를 지정하십시오 (예 :

private transient String name;

Gson 문서에 대한 자세한 내용


6
해당 클래스의 모든 인스턴스에 적용되는 제외 주석과 거의 동일합니다. 런타임 동적 제외를 원했습니다. 더 가벼운 / 제한된 응답을 제공하기 위해 일부 필드를 제외하고 싶은 경우도 있고 전체 개체를 직렬화하려는 경우도 있습니다.
— Liviu T.

34
한 가지 주목할 점은 일시적이 직렬화와 직렬화 해제에 영향을 미친다는 것입니다. JSON에 존재하더라도 값이 객체에 직렬화 된 값을 방출합니다.
— Kong

3
transient대신에 사용 하는 문제 @Expose는 들어오는 모든 필드를 사용하여 클라이언트에서 POJO를 여전히 조롱해야한다는 것입니다. 프로젝트간에 공유 될 수있는 백엔드 API의 경우 문제가 될 수 있습니다. 추가 필드가 추가됩니다. 기본적으로 필드의 허용 목록과 차단 목록입니다.
— theblang

11
이 방법은 gson 직렬화에서 필드를 제외했을뿐만 아니라 내부 응용 프로그램 직렬화 (Serializable 인터페이스 사용)에서 필드를 제외했기 때문에 저에게 효과적이지 않았습니다.
— pkk

8
transient는 필드의 직렬화 및 직렬화를 방지합니다. 이것은 내 요구와 일치하지 않습니다.
— Loenix

318

Nishant는 좋은 솔루션을 제공했지만 더 쉬운 방법이 있습니다. 다음과 같이 @Expose 주석으로 원하는 필드를 표시하십시오.

@Expose private Long id;

직렬화하지 않으려는 필드는 제외하십시오. 그런 다음 Gson 객체를 다음과 같이 만듭니다.

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

95
"notExpose"와 같은 것을 가질 수 있고 하나의 필드를 제외한 모든 필드를 직렬화해야하고 모든 필드에 주석을 추가하는 것이 중복되는 경우에만 무시할 수 있습니까?
— Daniil Shevelev

2
@DaSh 최근에 그러한 시나리오가있었습니다. 정확히 그렇게 한 맞춤형 ExclusionStrategy를 작성하는 것은 매우 쉬웠습니다. Nishant의 답변을 참조하십시오. 유일한 문제는 컨테이너 클래스와 스킵 클래스 대 스킵 필드를 가진 바이올린을 포함하는 것이 었습니다 (필드는 클래스가 될 수 있습니다 ...)
— keyser

1
@DaSh 아래의 대답 은 정확히 그렇게합니다.
— Derek Shockey

정말 좋은 해결책입니다. 디스크로 직렬화 된 필드를 원하지만 gson을 통해 서버로 보낼 때 무시되는 시나리오가 발생했습니다. 고마워요!
— Slynk

1
@Danlil @Expose (serialize = false, deserialize = false)를 사용할 수 있어야합니다
— Hrk

237

따라서 및 을 제외 firstName 하고 싶습니다 country.name. 당신의 ExclusionStrategy모습은 다음과 같습니다.

    public class TestExclStrat implements ExclusionStrategy {

        public boolean shouldSkipClass(Class<?> arg0) {
            return false;
        }

        public boolean shouldSkipField(FieldAttributes f) {

            return (f.getDeclaringClass() == Student.class && f.getName().equals("firstName"))||
            (f.getDeclaringClass() == Country.class && f.getName().equals("name"));
        }

    }

당신이 자세히 볼 경우 반환 true을 위해 Student.firstName및 Country.name제외 할 무엇이다.

이런 ExclusionStrategy식 으로 적용해야합니다

    Gson gson = new GsonBuilder()
        .setExclusionStrategies(new TestExclStrat())
        //.serializeNulls() <-- uncomment to serialize NULL fields as well
        .create();
    Student src = new Student();
    String json = gson.toJson(src);
    System.out.println(json);

이것은 다음을 반환합니다.

{ "middleName": "J.", "initials": "P.F", "lastName": "Fry", "country": { "id": 91}}

국가 객체가 id = 91L학생 클래스에서 초기화되었다고 가정합니다 .


당신은 공상을 얻을 수 있습니다. 예를 들어, 이름에 "name"문자열이 포함 된 필드를 직렬화하지 않으려 고합니다. 이 작업을 수행:

public boolean shouldSkipField(FieldAttributes f) {
    return f.getName().toLowerCase().contains("name"); 
}

이것은 다음을 반환합니다 :

{ "initials": "P.F", "country": { "id": 91 }}

편집 : 요청에 따라 더 많은 정보가 추가되었습니다.

이 작업 ExclusionStrategy이 수행되지만 "완전한 필드 이름"을 전달해야합니다. 아래를보십시오 :

    public class TestExclStrat implements ExclusionStrategy {

        private Class<?> c;
        private String fieldName;
        public TestExclStrat(String fqfn) throws SecurityException, NoSuchFieldException, ClassNotFoundException
        {
            this.c = Class.forName(fqfn.substring(0, fqfn.lastIndexOf(".")));
            this.fieldName = fqfn.substring(fqfn.lastIndexOf(".")+1);
        }
        public boolean shouldSkipClass(Class<?> arg0) {
            return false;
        }

        public boolean shouldSkipField(FieldAttributes f) {

            return (f.getDeclaringClass() == c && f.getName().equals(fieldName));
        }

    }

일반적인 사용법은 다음과 같습니다.

    Gson gson = new GsonBuilder()
        .setExclusionStrategies(new TestExclStrat("in.naishe.test.Country.name"))
        //.serializeNulls()
        .create();
    Student src = new Student();
    String json = gson.toJson(src);
    System.out.println(json); 

다음을 반환합니다.

{ "firstName": "Philip" , "middleName": "J.", "initials": "P.F", "lastName": "Fry", "country": { "id": 91 }}

답변 주셔서 감사합니다. 내가 원하는 것은 country.name필드 name를 직렬화 할 때 필드를 제외하고 문자열을 취할 수있는 ExclusionStrategy를 만드는 것입니다 country. Country 클래스의 country라는 속성이있는 모든 클래스에 적용 할 수있을 정도로 일반적이어야합니다. 모든 수업에 대해 ExclusionStrategy를 만들고 싶지 않습니다
— Liviu T.

@ Liviu T. 답변을 업데이트했습니다. 그것은 일반적인 접근 방식을 취합니다. 당신은 더 창조적이 될 수 있지만, 나는 그것을 정직하게 유지했습니다.
— Nishant

업데이트를 위해 타이. 내가; 객체 그래프에서 어디에서 메소드를 호출했는지 알 수 있는지 확인하기 위해 국가의 일부 필드를 제외 할 수 있지만 countryOfBirth (예 :)와 같은 클래스는 아니지만 속성이 다릅니다. 내가 달성하려는 것을 명확히하기 위해 내 질문을 편집했습니다
— Liviu T.

빈 값을 가진 필드를 제외하는 방법이 있습니까?
— Yusuf K.

12
이 답변은 기본 답변으로 표시해야합니다. 현재 더 많은 투표가있는 다른 답변과 달리이 솔루션에서는 Bean 클래스를 수정할 필요가 없습니다. 이것은 큰 장점입니다. 다른 사람이 같은 Bean 클래스를 사용하고 있고 "transient"로 유지하려는 필드를 표시 한 경우 어떻게합니까?
— user64141

221

사용 가능한 모든 답변을 읽은 후 가장 유연한 것은 사용자 정의 @Exclude주석 을 사용하는 것 입니다. 그래서 나는 이것을 위해 간단한 전략을 구현했다 (나는 모든 필드를 사용하여 표시하고 싶지 않았고 앱 직렬화 에서 충돌하는 @Expose것을 사용 하고 싶지 않았다 ).transientSerializable

주석:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Exclude {
}

전략:

public class AnnotationExclusionStrategy implements ExclusionStrategy {

    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return f.getAnnotation(Exclude.class) != null;
    }

    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }
}

용법:

new GsonBuilder().setExclusionStrategies(new AnnotationExclusionStrategy()).create();

16
추가로, 직렬화 또는 역 직렬화에만 제외 전략을 사용하려면 다음을 사용하십시오. 대신addSerializationExclusionStrategyaddDeserializationExclusionStrategysetExclusionStrategies
— GLee

9
완전한! DB 용 Realm을 사용하고 있고 Gson에서만 필드를 제외하고 있지만 Realm이 아닌 필드를 제외하고 싶기 때문에 임시 솔루션이 작동하지 않습니다.
— Marcio Granzotto

3
이것이 정답입니다. null 필드를 무시하려면 다음과 같이 변경하십시오 f.getAnnotation(Exclude.class) != null.f.getAnnotation(Exclude.class) == null
— Sharp Edge

3
transient다른 도서관의 요구 때문에 사용할 수 없을 때 좋습니다 . 감사!
— Martin D

1
안드로이드가 액티비티간에 클래스를 직렬화하기 때문에 나에게도 좋지만 GSON을 사용할 때만 제외하고 싶습니다. 이것은 내 앱이 다른 사람에게 보내기 위해 랩을 만들고 싶을 때까지 동일한 방식으로 계속 작동하게합시다.
— ThePartyTurtle

81

나는이 문제에 부딪쳤다.이 필드에는 직렬화에서만 제외하고 싶었던 소수의 필드가 있었으므로 @Expose맞춤형 제외 전략과 함께 Gson의 주석 을 사용하는 상당히 간단한 솔루션을 개발했다 .

사용하는 기본 제공 방법 @Expose은을 설정하는 GsonBuilder.excludeFieldsWithoutExposeAnnotation()것이지만 이름에서 알 수 있듯이 명시 적 필드가없는 필드 @Expose는 무시됩니다. 제외 할 필드가 몇 개 밖에 없었기 때문에 모든 필드에 주석을 추가 할 가능성이 매우 성가신 것으로 나타났습니다.

나는 @Expose그것을 배제하기 위해 명시 적으로 사용하지 않는 한 모든 것이 포함 된 역수를 효과적으로 원 했습니다. 이를 달성하기 위해 다음 제외 전략을 사용했습니다.

new GsonBuilder()
        .addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes fieldAttributes) {
                final Expose expose = fieldAttributes.getAnnotation(Expose.class);
                return expose != null && !expose.serialize();
            }

            @Override
            public boolean shouldSkipClass(Class<?> aClass) {
                return false;
            }
        })
        .addDeserializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes fieldAttributes) {
                final Expose expose = fieldAttributes.getAnnotation(Expose.class);
                return expose != null && !expose.deserialize();
            }

            @Override
            public boolean shouldSkipClass(Class<?> aClass) {
                return false;
            }
        })
        .create();

이제 몇 개의 필드 @Expose(serialize = false)또는 @Expose(deserialize = false)주석을 쉽게 제외 할 수 있습니다 (두 @Expose속성 의 기본값 은입니다 true). 물론 사용할 수 @Expose(serialize = false, deserialize = false)있지만 필드를 transient대신 선언하여 더 간결하게 수행 할 수 있습니다 (이러한 사용자 지정 제외 전략에는 여전히 적용됨).


효율성을 위해 일시적이지 않고 @Expose (serialize = false, deserialize = false)를 사용하는 경우를 볼 수 있습니다.
— paiego

1
@paiego 당신은 그것을 확장 할 수 있습니까? 나는 Gson 사용에서 수년이 지났으며 왜 주석이 일시적인 것으로 표시하는 것보다 효율적인지 이해할 수 없습니다.
— Derek Shockey

아, 실수를 저지른 점에 감사드립니다. 나는 일시적으로 휘발성을 취했다. (예를 들어, 캐싱이 없으므로 휘발성에 대한 캐시 일관성 문제는 없지만 성능이 떨어집니다) 어쨌든 코드는 훌륭하게 작동했습니다!
— paiego

18

gson으로 json 트리를 탐색 할 수 있습니다.

다음과 같이 해보십시오.

gson.toJsonTree(student).getAsJsonObject()
.get("country").getAsJsonObject().remove("name");

당신은 또한 몇 가지 속성을 추가 할 수 있습니다 :

gson.toJsonTree(student).getAsJsonObject().addProperty("isGoodStudent", false);

gson으로 테스트 2.2.4.


3
제거하기 전에 구문 분석 해야하는 복잡한 속성을 제거하려는 경우 이것이 너무 많은 성능 저하인지 궁금합니다. 생각?
— Ben

확실히 확장 가능한 솔루션은 아닙니다. 객체의 구조를 변경하거나 물건을 추가 / 제거 할 때 겪어야 할 모든 두통을 상상해보십시오.
— codenamezero

16

이 기능을 지원하기 위해 클래스 팩토리를 고안했습니다. 제외하려는 필드 또는 클래스의 조합을 전달하십시오.

public class GsonFactory {

    public static Gson build(final List<String> fieldExclusions, final List<Class<?>> classExclusions) {
        GsonBuilder b = new GsonBuilder();
        b.addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes f) {
                return fieldExclusions == null ? false : fieldExclusions.contains(f.getName());
            }

            @Override
            public boolean shouldSkipClass(Class<?> clazz) {
                return classExclusions == null ? false : classExclusions.contains(clazz);
            }
        });
        return b.create();

    }
}

사용하려면 두 개의 목록을 만들고 (각각 선택 사항 임) GSON 객체를 만듭니다.

static {
 List<String> fieldExclusions = new ArrayList<String>();
 fieldExclusions.add("id");
 fieldExclusions.add("provider");
 fieldExclusions.add("products");

 List<Class<?>> classExclusions = new ArrayList<Class<?>>();
 classExclusions.add(Product.class);
 GSON = GsonFactory.build(null, classExclusions);
}

private static final Gson GSON;

public String getSomeJson(){
    List<Provider> list = getEntitiesFromDatabase();
    return GSON.toJson(list);
}

물론 이것은 속성의 정규화 된 이름을보고 일치하는 경우 제외하도록 수정할 수 있습니다.
— Domenic D.

아래 예제를하고 있습니다. 작동하지 않습니다. Pls는 개인 정적 최종 Gson GSON을 제안합니다. static {List <String> fieldExclusions = 새로운 ArrayList <String> (); fieldExclusions.add ( "id"); GSON = GsonFactory.build (fieldExclusions, null); } private static String getSomeJson () {String jsonStr = "[{\"id \ ": 111, \"name \ ": \"praveen \ ", \"age \ ": 16}, {\"id \ ": 222, \ "이름 \": \ "취약 제 \", \ "나이 \": 20}] "; jsonStr을 리턴; } public static void main (String [] args) {문자열 jsonStr = getSomeJson (); System.out.println (GSON.toJson (jsonStr)); }
— Praveen Hiremath

13

사용자 지정 주석 으로이 문제를 해결했습니다. 이것은 나의 "SkipSerialisation"주석 클래스입니다 :

@Target (ElementType.FIELD)
public @interface SkipSerialisation {

}

그리고 이것은 내 GsonBuilder입니다.

gsonBuilder.addSerializationExclusionStrategy(new ExclusionStrategy() {

  @Override public boolean shouldSkipField (FieldAttributes f) {

    return f.getAnnotation(SkipSerialisation.class) != null;

  }

  @Override public boolean shouldSkipClass (Class<?> clazz) {

    return false;
  }
});

예 :

public class User implements Serializable {

  public String firstName;

  public String lastName;

  @SkipSerialisation
  public String email;
}

5
Gson : 주석없이
— Ben

3
@Retention(RetentionPolicy.RUNTIME)주석에 추가 해야합니다.
— David Novák

9

또는 어떤 필드에 노출되지 않을 것인지 말할 수 있습니다.

Gson gson = gsonBuilder.excludeFieldsWithModifiers(Modifier.TRANSIENT).create();

속성에 대한 클래스 :

private **transient** boolean nameAttribute;

17
임시 및 정적 필드는 기본적으로 제외됩니다. 그럴 필요가 없습니다 excludeFieldsWithModifiers().
— Derek Shockey

9

이 전략을 사용했습니다. @SerializedName 주석으로 표시 되지 않은 모든 필드를 제외했습니다 .

public class Dummy {

    @SerializedName("VisibleValue")
    final String visibleValue;
    final String hiddenValue;

    public Dummy(String visibleValue, String hiddenValue) {
        this.visibleValue = visibleValue;
        this.hiddenValue = hiddenValue;
    }
}


public class SerializedNameOnlyStrategy implements ExclusionStrategy {

    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return f.getAnnotation(SerializedName.class) == null;
    }

    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }
}


Gson gson = new GsonBuilder()
                .setExclusionStrategies(new SerializedNameOnlyStrategy())
                .create();

Dummy dummy = new Dummy("I will see this","I will not see this");
String json = gson.toJson(dummy);

반환

{ "VisibleValue": "이것을 볼 것입니다"}


6

또 다른 방법은 (런타임에 필드를 제외하기로 결정한 경우 특히 유용합니다) gson 인스턴스에 TypeAdapter를 등록하는 것입니다. 아래 예 :

Gson gson = new GsonBuilder()
.registerTypeAdapter(BloodPressurePost.class, new BloodPressurePostSerializer())

아래의 경우 서버는 두 값 중 하나를 기대하지만 둘 다 정수이므로 gson은 두 값을 직렬화합니다. 내 목표는 서버에 게시 된 json에서 0 이하의 값을 생략하는 것이 었습니다.

public class BloodPressurePostSerializer implements JsonSerializer<BloodPressurePost> {

    @Override
    public JsonElement serialize(BloodPressurePost src, Type typeOfSrc, JsonSerializationContext context) {
        final JsonObject jsonObject = new JsonObject();

        if (src.systolic > 0) {
            jsonObject.addProperty("systolic", src.systolic);
        }

        if (src.diastolic > 0) {
            jsonObject.addProperty("diastolic", src.diastolic);
        }

        jsonObject.addProperty("units", src.units);

        return jsonObject;
    }
}

6

Kotlin의 @Transient주석은 분명히 트릭을 수행합니다.

data class Json(
    @field:SerializedName("serialized_field_1") val field1: String,
    @field:SerializedName("serialized_field_2") val field2: String,
    @Transient val field3: String
)

산출:

{"serialized_field_1":"VALUE1","serialized_field_2":"VALUE2"}

1

나는 @Expose주석 을 넣는 것만으로 노력하고 있습니다.

compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

에서 Model클래스 :

@Expose
int number;

public class AdapterRestApi {

에서 Adapter클래스 :

public EndPointsApi connectRestApi() {
    OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(90000, TimeUnit.SECONDS)
            .readTimeout(90000,TimeUnit.SECONDS).build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(ConstantRestApi.ROOT_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build();

    return retrofit.create  (EndPointsApi.class);
}

1

Kotlin 버전이 있습니다

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
internal annotation class JsonSkip

class SkipFieldsStrategy : ExclusionStrategy {

    override fun shouldSkipClass(clazz: Class<*>): Boolean {
        return false
    }

    override fun shouldSkipField(f: FieldAttributes): Boolean {
        return f.getAnnotation(JsonSkip::class.java) != null
    }
}

Retrofit GSONConverterFactory에 추가하는 방법 :

val gson = GsonBuilder()
                .setExclusionStrategies(SkipFieldsStrategy())
                //.serializeNulls()
                //.setDateFormat(DateFormat.LONG)
                //.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
                //.setPrettyPrinting()
                //.registerTypeAdapter(Id.class, IdTypeAdapter())
                .create()
        return GsonConverterFactory.create(gson)

0

내가 항상 사용하는 것 :

Gson에서 구현 된 기본 동작은 null 개체 필드가 ​​무시되는 것입니다.

Gson 객체가 null 값을 가진 필드를 JSON으로 직렬화하지 않음을 의미합니다. Java 객체의 필드가 null이면 Gson에서 제외합니다.

이 함수를 사용하여 일부 객체를 null로 변환하거나 자체적으로 잘 설정할 수 있습니다

     /**
   * convert object to json
   */
  public String toJson(Object obj) {
    // Convert emtpy string and objects to null so we don't serialze them
    setEmtpyStringsAndObjectsToNull(obj);
    return gson.toJson(obj);
  }

  /**
   * Sets all empty strings and objects (all fields null) including sets to null.
   *
   * @param obj any object
   */
  public void setEmtpyStringsAndObjectsToNull(Object obj) {
    for (Field field : obj.getClass().getDeclaredFields()) {
      field.setAccessible(true);
      try {
        Object fieldObj = field.get(obj);
        if (fieldObj != null) {
          Class fieldType = field.getType();
          if (fieldType.isAssignableFrom(String.class)) {
            if(fieldObj.equals("")) {
              field.set(obj, null);
            }
          } else if (fieldType.isAssignableFrom(Set.class)) {
            for (Object item : (Set) fieldObj) {
              setEmtpyStringsAndObjectsToNull(item);
            }
            boolean setFielToNull = true;
            for (Object item : (Set) field.get(obj)) {
              if(item != null) {
                setFielToNull = false;
                break;
              }
            }
            if(setFielToNull) {
              setFieldToNull(obj, field);
            }
          } else if (!isPrimitiveOrWrapper(fieldType)) {
            setEmtpyStringsAndObjectsToNull(fieldObj);
            boolean setFielToNull = true;
            for (Field f : fieldObj.getClass().getDeclaredFields()) {
              f.setAccessible(true);
              if(f.get(fieldObj) != null) {
                setFielToNull = false;
                break;
              }
            }
            if(setFielToNull) {
              setFieldToNull(obj, field);
            }
          }
        }
      } catch (IllegalAccessException e) {
        System.err.println("Error while setting empty string or object to null: " + e.getMessage());
      }
    }
  }

  private void setFieldToNull(Object obj, Field field) throws IllegalAccessException {
    if(!Modifier.isFinal(field.getModifiers())) {
      field.set(obj, null);
    }
  }

  private boolean isPrimitiveOrWrapper(Class fieldType)  {
    return fieldType.isPrimitive()
        || fieldType.isAssignableFrom(Integer.class)
        || fieldType.isAssignableFrom(Boolean.class)
        || fieldType.isAssignableFrom(Byte.class)
        || fieldType.isAssignableFrom(Character.class)
        || fieldType.isAssignableFrom(Float.class)
        || fieldType.isAssignableFrom(Long.class)
        || fieldType.isAssignableFrom(Double.class)
        || fieldType.isAssignableFrom(Short.class);
  }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.