[英]Jackson Custom Deserialize
我想反序列化我的自定義序列化對象。 我的對象基本上是一個簡單的Pair實現。
class School{
Integer id;
String schoolName;
}
class Student{
Integer id;
Integer schoolId;
String studentName;
}
@JsonSerialize(using=PairSerializer.class)
public class Pair<V,K>{
V v;
K k;
}
這是結果
[
{
"v":{
"id":1,
"schoolId":3,
"studentName":"O. Bas"
},
"k":{
"id":3,
"schoolName":"School 3"
}
},
{
"v":{
"id":2,
"schoolId":3,
"studentName":"C. Koc"
},
"k":{
"id":3,
"schoolName":"School 3"
}
}
]
v和k作為json中的字段名稱非常難看。 這就是我編寫自定義序列化程序的原因:
@Override
public void serialize(Pair pair, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectField(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL,pair.getK().getClass().getSimpleName() ), pair.getK());
jsonGenerator.writeObjectField(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL,pair.getV().getClass().getSimpleName() ), pair.getV());
jsonGenerator.writeEndObject();
}
結果正是我想要的。 v和k字段名稱由其類名替換。
[
{
"school":{
"id":3,
"schoolName":"School 3"
},
"student":{
"id":1,
"schoolId":3,
"studentName":"O. Bas"
}
},
{
"school":{
"id":3,
"schoolName":"School 3"
},
"student":{
"id":2,
"schoolId":3,
"studentName":"C. Koc"
}
}
]
這是我的問題。 如何將我的json字符串反序列化為List<Pair<V, K>
? 真正的問題是V和K取決於反序列化的上下文,它可能會隨學生,學校或另一對實現而變化。
public class PairDeserializer extends JsonDeserializer<Pair> {
public PairDeserializer() {
}
@Override
public Pair deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
// I need to Deserialized generic type information of Pair
}
}
我想,您應該創建自己的PropertyNamingStrategy
。 例如,請參閱我的簡單實現:
class MapTransformNamingStrategy extends LowerCaseWithUnderscoresStrategy {
private static final long serialVersionUID = 1L;
private Map<String, String> mapping;
public MapTransformNamingStrategy(Map<String, String> mapping) {
this.mapping = mapping;
}
@Override
public String translate(String property) {
if (mapping.containsKey(property)) {
return mapping.get(property);
}
return property;
}
}
現在您可以這樣使用它:
Map<String, String> mapping = new HashMap<String, String>();
mapping.put("k", "student");
mapping.put("v", "school");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setPropertyNamingStrategy(new MapTransformNamingStrategy(mapping));
//etc
示例JSON輸出:
{ "school" : { "id" : 1,
"schoolName" : "The Best School in the world"
},
"student" : { "id" : 1,
"schoolId" : 1,
"studentName" : "Arnold Shwarz"
}
}
編輯
因為我的回答並不清楚,所以我提供了完整的示例源代碼,它將Java POJO對象序列化為JSON,反之亦然。
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy;
public class JacksonProgram {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
List<Pair<Student, School>> pairs = createDataForSerialization();
Map<String, String> mapping = createSchoolStudentMapping();
JsonConverter jsonConverter = new JsonConverter(mapping);
String json = jsonConverter.toJson(pairs);
System.out.println("JSON which represents list of pairs:");
System.out.println(json);
List<Pair<Student, School>> value = jsonConverter.fromJson(json, List.class);
System.out.println("----");
System.out.println("Deserialized version:");
System.out.println(value);
}
private static Map<String, String> createSchoolStudentMapping() {
Map<String, String> mapping = new HashMap<String, String>();
mapping.put("k", "student");
mapping.put("v", "school");
return mapping;
}
private static List<Pair<Student, School>> createDataForSerialization() {
List<Pair<Student, School>> pairs = new ArrayList<Pair<Student, School>>();
pairs.add(new Pair<Student, School>(new Student(1, 3, "O. Bas"), new School(3, "School 3")));
pairs.add(new Pair<Student, School>(new Student(2, 4, "C. Koc"), new School(4, "School 4")));
return pairs;
}
}
class JsonConverter {
private Map<String, String> mapping;
private ObjectMapper objectMapper;
private JsonFactory jsonFactory;
public JsonConverter(Map<String, String> mapping) {
this.mapping = mapping;
initJsonObjects();
}
private void initJsonObjects() {
objectMapper = new ObjectMapper();
objectMapper.setPropertyNamingStrategy(new MapTransformNamingStrategy(mapping));
jsonFactory = new JsonFactory();
}
public String toJson(Object object) throws Exception {
StringWriter stringWriter = new StringWriter();
JsonGenerator jsonGenerator = jsonFactory.createGenerator(stringWriter);
objectMapper.writeValue(jsonGenerator, object);
return stringWriter.toString();
}
public <T> T fromJson(String json, Class<T> expectedType) throws Exception {
JsonParser jsonParser = jsonFactory.createJsonParser(json);
return objectMapper.readValue(jsonParser, expectedType);
}
}
class MapTransformNamingStrategy extends LowerCaseWithUnderscoresStrategy {
private static final long serialVersionUID = 1L;
private Map<String, String> mapping;
public MapTransformNamingStrategy(Map<String, String> mapping) {
this.mapping = mapping;
}
@Override
public String translate(String property) {
if (mapping.containsKey(property)) {
return mapping.get(property);
}
return property;
}
}
class School {
private Integer id;
private String schoolName;
public School() {
}
public School(Integer id, String schoolName) {
this.id = id;
this.schoolName = schoolName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSchoolName() {
return schoolName;
}
public void setSchoolName(String schoolName) {
this.schoolName = schoolName;
}
@Override
public String toString() {
return "School [id=" + id + ", schoolName=" + schoolName + "]";
}
}
class Student {
private Integer id;
private Integer schoolId;
private String studentName;
public Student() {
}
public Student(Integer id, Integer schoolId, String studentName) {
this.id = id;
this.schoolId = schoolId;
this.studentName = studentName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getSchoolId() {
return schoolId;
}
public void setSchoolId(Integer schoolId) {
this.schoolId = schoolId;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
@Override
public String toString() {
return "Student [id=" + id + ", schoolId=" + schoolId + ", studentName=" + studentName
+ "]";
}
}
class Pair<V, K> {
private V v;
private K k;
public Pair() {
}
public Pair(V v, K k) {
this.v = v;
this.k = k;
}
public V getV() {
return v;
}
public void setV(V v) {
this.v = v;
}
public K getK() {
return k;
}
public void setK(K k) {
this.k = k;
}
@Override
public String toString() {
return "Pair [v=" + v + ", k=" + k + "]";
}
}
完整輸出日志:
JSON which represents list of pairs:
[{"school":{"id":1,"schoolId":3,"studentName":"O. Bas"},"student":{"id":3,"schoolName":"School 3"}},{"school":{"id":2,"schoolId":4,"studentName":"C. Koc"},"student":{"id":4,"schoolName":"School 4"}}]
----
Deserialized version:
[{school={id=1, schoolId=3, studentName=O. Bas}, student={id=3, schoolName=School 3}}, {school={id=2, schoolId=4, studentName=C. Koc}, student={id=4, schoolName=School 4}}]
因為輸出JSON沒有格式化,所以我將它呈現在更易於理解的版本中:
[
{
"school":{
"id":1,
"schoolId":3,
"studentName":"O. Bas"
},
"student":{
"id":3,
"schoolName":"School 3"
}
},
{
"school":{
"id":2,
"schoolId":4,
"studentName":"C. Koc"
},
"student":{
"id":4,
"schoolName":"School 4"
}
}
]
如您所見,我們創建了新的JsonConverter
對象,其中定義了Pair
屬性名稱之間的映射以及我們希望在JSON字符串表示中看到的名稱。 現在,如果你有例如Pair<School, Room>
你可以用這種方式創建映射Map:
private static Map<String, String> createSchoolRoomMapping() {
Map<String, String> mapping = new HashMap<String, String>();
mapping.put("k", "school");
mapping.put("v", "room");
return mapping;
}
我正在尋找帶有一些注釋的答案( JsonTypeInfo
和JsonUnwrapped
),但這兩個顯然不能很好地協同工作(參見本期 )。 這將處理您的問題的序列化和反序列化部分,而不依賴於自定義de / serializer。 相反,你需要一個自定義反序列化器,它在這些行上做了一些事情:
class PairDeserializer extends JsonDeserializer<Pair>{
static Map<String, Class> MAPPINGS = new HashMap<String, Class>();
@Override
public Pair deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
Object key = deserializeField(jp);
Object value = deserializeField(jp);
Pair pair = new Pair();
pair.k = key;
pair.v = value;
jp.nextToken();
return pair;
}
private Object deserializeField(JsonParser jp) throws IOException, JsonParseException, JsonProcessingException {
jp.nextValue();
String className = jp.getCurrentName();
return jp.readValueAs(MAPPINGS.get(className));
}
}
然后,您只需要注冊所需的映射
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.