나는 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
. 또한 국가를 유형으로 제외하고 싶지 않습니다. 따라서 유형은 객체 그래프에서 정확히 지적하고 제외하려는 실제 위치와 동일합니다.
답변
일반적으로 직렬화하지 않으려는 모든 필드는 “일시적”수정자를 사용해야하며 이는 json 직렬화 기에도 적용됩니다 (적어도 gson을 포함하여 내가 사용한 몇 가지에 해당).
직렬화 된 json에 이름을 표시하지 않으려면 임시 키워드를 지정하십시오 (예 :
private transient String name;
답변
Nishant는 좋은 솔루션을 제공했지만 더 쉬운 방법이 있습니다. 다음과 같이 @Expose 주석으로 원하는 필드를 표시하십시오.
@Expose private Long id;
직렬화하지 않으려는 필드는 제외하십시오. 그런 다음 Gson 객체를 다음과 같이 만듭니다.
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
답변
따라서 및 을 제외 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 }}
답변
사용 가능한 모든 답변을 읽은 후 가장 유연한 것은 사용자 정의 @Exclude
주석 을 사용하는 것 입니다. 그래서 나는 이것을 위해 간단한 전략을 구현했다 (나는 모든 필드를 사용하여 표시하고 싶지 않았고 앱 직렬화 에서 충돌하는 @Expose
것을 사용 하고 싶지 않았다 ).transient
Serializable
주석:
@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();
답변
나는이 문제에 부딪쳤다.이 필드에는 직렬화에서만 제외하고 싶었던 소수의 필드가 있었으므로 @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
대신 선언하여 더 간결하게 수행 할 수 있습니다 (이러한 사용자 지정 제외 전략에는 여전히 적용됨).
답변
gson으로 json 트리를 탐색 할 수 있습니다.
다음과 같이 해보십시오.
gson.toJsonTree(student).getAsJsonObject()
.get("country").getAsJsonObject().remove("name");
당신은 또한 몇 가지 속성을 추가 할 수 있습니다 :
gson.toJsonTree(student).getAsJsonObject().addProperty("isGoodStudent", false);
gson으로 테스트 2.2.4.
답변
이 기능을 지원하기 위해 클래스 팩토리를 고안했습니다. 제외하려는 필드 또는 클래스의 조합을 전달하십시오.
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);
}