To może być duplikat. Ale nie mogę znaleźć rozwiązania mojego problemu.
mam klasę
public class MyResponse implements Serializable {
private boolean isSuccess;
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
}
Metody pobierające i ustawiające są generowane przez Eclipse.
W innej klasie ustawiam wartość na true i zapisuję ją jako ciąg JSON.
System.out.println(new ObjectMapper().writeValueAsString(myResponse));
W JSON klucz pojawia się jako {"success": true}
.
Chcę, żeby klucz był isSuccess
sobą. Czy Jackson używa metody ustawiającej podczas serializacji? Jak nadać kluczowi samą nazwę pola?
isSuccess
, nazwa metody musi być takisIsSuccess
myślęSetSuccess
ponieważ jest generowany przez Eclipse. (Zgodnie ze standardem)Odpowiedzi:
To trochę późna odpowiedź, ale może być przydatna dla każdego, kto odwiedza tę stronę.
Prostym rozwiązaniem zmiany nazwy, której będzie używał Jackson podczas serializacji do formatu JSON, jest użycie adnotacji @JsonProperty , więc przykład będzie wyglądał następująco:
public class MyResponse implements Serializable { private boolean isSuccess; @JsonProperty(value="isSuccess") public boolean isSuccess() { return isSuccess; } public void setSuccess(boolean isSuccess) { this.isSuccess = isSuccess; } }
Byłoby to następnie serializowane do formatu JSON jako
{"isSuccess":true}
, ale ma tę zaletę, że nie trzeba modyfikować nazwy metody pobierającej.Zauważ, że w tym przypadku możesz również napisać adnotację, ponieważ
@JsonProperty("isSuccess")
ma ona tylko jedenvalue
elementźródło
Niedawno natknąłem się na ten problem i oto, co znalazłem. Jackson sprawdzi każdą przekazaną do niej klasę pod kątem metod pobierających i ustawiających i użyje tych metod do serializacji i deserializacji. To, co następuje po wyrażeniach „get”, „is” i „set” w tych metodach, zostanie użyte jako klucz dla pola JSON („isValid” dla getIsValid i setIsValid).
public class JacksonExample { private boolean isValid = false; public boolean getIsValid() { return isValid; } public void setIsValid(boolean isValid) { this.isValid = isValid; } }
Podobnie „isSuccess” stanie się „sukcesem”, chyba że zostanie zmieniona na „isIsSuccess” lub „getIsSuccess”
Przeczytaj więcej tutaj: http://www.citrine.io/blog/2015/5/20/jackson-json-processor
źródło
Użycie obu poniższych adnotacji wymusza uwzględnienie w wyjściowym formacie JSON
is_xxx
:@get:JsonProperty("is_something") @param:JsonProperty("is_something")
źródło
Możesz skonfigurować
ObjectMapper
następujące opcje:mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() { @Override public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class) && method.getName().startsWith("is")) { return method.getName(); } return super.nameForGetterMethod(config, method, defaultName); } });
źródło
Gdy używasz Kotlin i klas danych:
data class Dto( @get:JsonProperty("isSuccess") val isSuccess: Boolean )
Może być konieczne dodanie,
@param:JsonProperty("isSuccess")
jeśli zamierzasz również deserializować JSON.źródło
Opierając się na odpowiedzi Utkarsha ...
Nazwy metody pobierania minus get / jest używane jako nazwa JSON.
public class Example{ private String radcliffe; public getHarryPotter(){ return radcliffe; } }
jest przechowywany jako {"harryPotter": "cokolwiekYouGaveHere"}
W przypadku deserializacji Jackson sprawdza zarówno ustawiającego, jak i nazwę pola. W przypadku ciągu Json {"word1": "example"} oba poniższe są prawidłowe.
public class Example{ private String word1; public setword2( String pqr){ this.word1 = pqr; } } public class Example2{ private String word2; public setWord1(String pqr){ this.word2 = pqr ; } }
Bardziej interesującym pytaniem jest to, który porządek Jackson rozważa przy deserializacji. Jeśli spróbuję deserializować {"word1": "myName"} z
public class Example3{ private String word1; private String word2; public setWord1( String parameter){ this.word2 = parameter ; } }
Nie testowałem powyższego przypadku, ale byłoby interesujące zobaczyć wartości word1 i word2 ...
Uwaga: użyłem drastycznie różnych nazw, aby podkreślić, które pola muszą być takie same.
źródło
istnieje inna metoda rozwiązania tego problemu.
wystarczy zdefiniować nową podklasę, która rozszerza PropertyNamingStrategy i przekazuje ją do instancji ObjectMapper.
tutaj fragment kodu może być bardziej pomocny:
mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() { @Override public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { String input = defaultName; if(method.getName().startsWith("is")){ input = method.getName(); } //copy from LowerCaseWithUnderscoresStrategy if (input == null) return input; // garbage in, garbage out int length = input.length(); StringBuilder result = new StringBuilder(length * 2); int resultLength = 0; boolean wasPrevTranslated = false; for (int i = 0; i < length; i++) { char c = input.charAt(i); if (i > 0 || c != '_') // skip first starting underscore { if (Character.isUpperCase(c)) { if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_') { result.append('_'); resultLength++; } c = Character.toLowerCase(c); wasPrevTranslated = true; } else { wasPrevTranslated = false; } result.append(c); resultLength++; } } return resultLength > 0 ? result.toString() : input; } });
źródło
Nie chciałem mieszać z niektórymi niestandardowymi strategiami nazewnictwa ani ponownie tworzyć niektórych akcesorów.
Im mniej kodu, tym jestem szczęśliwszy.
To załatwiło nam sprawę:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; @JsonIgnoreProperties({"success", "deleted"}) // <- Prevents serialization duplicates public class MyResponse { private String id; private @JsonProperty("isSuccess") boolean isSuccess; // <- Forces field name private @JsonProperty("isDeleted") boolean isDeleted; }
źródło
Zaakceptowana odpowiedź nie będzie działać w moim przypadku.
W moim przypadku klasa nie jest moją własnością. Problematyczna klasa pochodzi z zależności innych firm, więc nie mogę po prostu dodać
@JsonProperty
adnotacji.Aby rozwiązać ten problem, zainspirowany powyższą odpowiedzią @burak, stworzyłem następujący zwyczaj
PropertyNamingStrategy
:mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() { @Override public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { if (method.getParameterCount() == 1 && (method.getRawParameterType(0) == Boolean.class || method.getRawParameterType(0) == boolean.class) && method.getName().startsWith("set")) { Class<?> containingClass = method.getDeclaringClass(); String potentialFieldName = "is" + method.getName().substring(3); try { containingClass.getDeclaredField(potentialFieldName); return potentialFieldName; } catch (NoSuchFieldException e) { // do nothing and fall through } } return super.nameForSetterMethod(config, method, defaultName); } @Override public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class) && method.getName().startsWith("is")) { Class<?> containingClass = method.getDeclaringClass(); String potentialFieldName = method.getName(); try { containingClass.getDeclaredField(potentialFieldName); return potentialFieldName; } catch (NoSuchFieldException e) { // do nothing and fall through } } return super.nameForGetterMethod(config, method, defaultName); } });
Zasadniczo co to robi to przed szeregowania i deserializacji, sprawdza się w docelowej klasie / Nazwa obiektu źródłowego, który jest obecny w klasie, czy jest
isEnabled
lubenabled
nieruchomość.Na tej podstawie program mapujący będzie serializował i deserializował do istniejącej nazwy właściwości.
źródło
Możesz zmienić pierwotną wartość logiczną na java.lang.Boolean (+ użyj
@JsonPropery
)@JsonProperty("isA") private Boolean isA = false; public Boolean getA() { return this.isA; } public void setA(Boolean a) { this.isA = a; }
U mnie zadziałało doskonale.
źródło