我遇到了与杰克逊对象去除物品的问题。问题是,在我收到的json中,同一个字段有时会有不同的名称。
例如:
{ "author": { "ce:surname": "Chia" } }
或:
{ "author": { "surname": "Woods" } }
甚至:
{ "author": { "preferred-name": { "surname": "Woods" }} }
实际的json文件要大得多,我已将其简化以显示问题。
我想将它反序列化为一个简单的类:
public class Author {
public String surname;
}
杰克逊是否可以在不创建自定义JsonDeserializer的情况下使用?我不能修改原来的json,它不是由我生成的。
我正在使用Jackson 2.5.0版本
更新:我已经解决了这个问题。这是实际JSON的一部分,我需要解析:
"authors": {
"author": [
{
"@_fa": "true",
"@auid": "55126316600",
"@seq": "1",
"affiliation": {
"@href": "http://api.elsevier.com/content/affiliation/affiliation_id/60031101",
"@id": "60031101"
},
"author-url": "http://api.elsevier.com/content/author/author_id/55126316600",
"ce:indexed-name": "Chia C.S.B.",
"ce:initials": "C.S.B.",
"ce:surname": "Chia",
"preferred-name": {
"ce:given-name": "C. S B",
"ce:indexed-name": "Chia C.",
"ce:initials": "C.S.B.",
"ce:surname": "Chia"
}
},... ]}
我需要将它编组成一个Author []数组:
public class Author {
private final String authorId;
private final String authorUrl;
private final String fullName;
private final String givenName;
private final String familyName;
private final String initials;
public Author(
final String authorId,
final String authorUrl,
final String fullName,
final String givenName,
final String familyName,
final String initials) {
this.authorId = authorId;
this.authorUrl = authorUrl;
this.fullName = fullName;
this.givenName = givenName;
this.familyName = familyName;
this.initials = initials;
}
public String getAuthorId() {
return authorId;
}
public String getAuthorUrl() {
return authorUrl;
}
public String getFullName() {
return fullName;
}
public String getGivenName() {
return givenName;
}
public String getFamilyName() {
return familyName;
}
public String getInitials() {
return initials;
}
}
我为此创建了两个自定义deserealizer:
public class AuthorDeserializer extends JsonDeserializer<Author> {
private static final String JSON_AUID = "@auid";
private static final String JSON_AUTHOR_URL = "author-url";
private static final String JSON_CE_INDEXED_NAME = "ce:indexed-name";
private static final String JSON_CE_GIVEN_NAME = "ce:given-name";
private static final String JSON_CE_SURNAME = "ce:surname";
private static final String JSON_CE_INNITIALS = "ce:initials";
private static final String JSON_PREFERRED_NAME = "preferred-name";
private static final String PROPERTY_AUTHOR_ID = "authorId";
private static final String PROPERTY_AUTHOR_URL = "authorUrl";
private static final String PROPERTY_FULL_NAME = "fullName";
private static final String PROPERTY_GIVEN_NAME = "familyName";
private static final String PROPERTY_FAMILY_NAME = "familyName";
private static final String PROPERTY_INITIALS = "initials";
protected List<Object> parseArray(JsonParser jp) throws IOException {
List<Object> list = null;
for(JsonToken token = jp.nextToken(); token != null && token != JsonToken.END_ARRAY; token = jp.nextToken()) {
if (token != JsonToken.START_OBJECT)
throw new IOException("Wrong object start token: "+jp.getCurrentToken());
Object value = parseObject(jp);
if (null == list)
list = new ArrayList<Object>();
list.add(value);
}
return list;
}
protected Map<String, Object> parseObject(JsonParser jp) throws IOException {
// create empty map
Map<String, Object> map = null;
// run the main cicle until we will actually get end of the object
for(JsonToken token = jp.nextToken(); token != null && token != JsonToken.END_OBJECT; token = jp.nextToken()) {
// check that next object is a field name
if (token != JsonToken.FIELD_NAME)
throw new IOException("Wrong object field token: "+jp.getCurrentToken());
// retrive object field key
String key = jp.getCurrentName();
Object value = null;
// go to the next token
token = jp.nextToken();
if (token == JsonToken.START_ARRAY)
value = parseArray(jp);
else if (token == JsonToken.START_OBJECT)
value = parseObject(jp);
else if (token == JsonToken.VALUE_STRING)
value = jp.getValueAsString();
else if (token == JsonToken.VALUE_NUMBER_INT)
value = jp.getValueAsDouble();
else if (token == JsonToken.VALUE_NUMBER_INT)
value = jp.getIntValue();
else if (token == JsonToken.VALUE_TRUE)
value = true;
else if (token == JsonToken.VALUE_FALSE)
value = false;
else
value = null;
if (null == map)
map = new HashMap<String, Object>();
map.put(key, value);
}
return map;
}
protected Object parse(JsonParser jp) throws IOException {
Object object = null;
JsonToken token = jp.getCurrentToken();
if (token == JsonToken.START_ARRAY)
object = parseArray(jp);
else if (token == JsonToken.START_OBJECT)
object = parseObject(jp);
else
throw new IOException("Wrong start token: "+jp.getCurrentToken()+". The START_ARRAY or START_OBJECT expected");
return object;
}
public void putIfAbsent(Map<String, Object> src, Map<String, Object> dst, String keySrc, String keyDst) {
if (!dst.containsKey(keyDst) && src.get(keySrc) != null)
dst.put(keyDst, src.get(keySrc));
}
@Override
public Author deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
Map<String, Object> author = new HashMap<String, Object>();
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) parse(jp);
putIfAbsent(map, author, JSON_AUID, PROPERTY_AUTHOR_ID);
putIfAbsent(map, author, JSON_AUTHOR_URL, PROPERTY_AUTHOR_URL);
putIfAbsent(map, author, JSON_CE_INDEXED_NAME, PROPERTY_FULL_NAME);
putIfAbsent(map, author, JSON_CE_INNITIALS, PROPERTY_INITIALS);
putIfAbsent(map, author, JSON_CE_SURNAME, PROPERTY_FAMILY_NAME);
putIfAbsent(map, author, JSON_CE_GIVEN_NAME, PROPERTY_GIVEN_NAME);
@SuppressWarnings("unchecked")
Map<String, Object> prefered = (Map<String, Object>) map.get(JSON_PREFERRED_NAME);
if (null != prefered) {
putIfAbsent(prefered, author, JSON_CE_INDEXED_NAME, PROPERTY_FULL_NAME);
putIfAbsent(prefered, author, JSON_CE_INNITIALS, PROPERTY_INITIALS);
putIfAbsent(prefered, author, JSON_CE_SURNAME, PROPERTY_FAMILY_NAME);
putIfAbsent(prefered, author, JSON_CE_GIVEN_NAME, PROPERTY_GIVEN_NAME);
}
return new Author(
(String) author.get(PROPERTY_AUTHOR_ID),
(String) author.get(PROPERTY_AUTHOR_URL),
(String) author.get(PROPERTY_FULL_NAME),
(String) author.get(PROPERTY_GIVEN_NAME),
(String) author.get(PROPERTY_FAMILY_NAME),
(String) author.get(PROPERTY_INITIALS));
}
}
和包装器对象:
public class AuthorsDeserealizer extends JsonDeserializer<Author[]>{
private static final String JSON_AUTHOR = "author";
@Override
public Author[] deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
if (jp.getCurrentToken() != JsonToken.START_OBJECT)
throw new IOException("Wrong author object start token: "+jp.getCurrentToken());
if (jp.nextToken() != JsonToken.FIELD_NAME)
throw new IOException("Wrong author field token: "+jp.getCurrentToken());
if (!jp.getCurrentName().equals(JSON_AUTHOR))
throw new IOException("Wrong author field: "+jp.getCurrentName());
if (jp.nextToken() != JsonToken.START_ARRAY)
throw new IOException("Wrong author array start token: "+jp.getCurrentToken());
jp.nextToken();
ArrayList<Author> list = Lists.newArrayList(jp.readValuesAs(Author.class));
if (jp.getCurrentToken() != JsonToken.END_ARRAY)
throw new IOException("Wrong author array end token: "+jp.getCurrentToken());
if (jp.nextToken() != JsonToken.END_OBJECT)
throw new IOException("Wrong author object end token: "+jp.getCurrentToken());
return list.toArray(new Author[list.size()]);
}
}
解决方案看起来很难看但有效。以太,如果有人能给我一个更好的解决方案,我会接受这个答案。感谢。
答案 0 :(得分:1)
一种方法是创建多个&#34; setter&#34;方法,如:
public class Author {
public String surname;
// name of method irrelevant when using annotation
@JsonProperty("preferred-name")
public void alternate2(String n) { surname = n; }
@JsonProperty("ce:surname")
public void alternate3(String n) { surname = n; }
}
其中三个不同的属性名称都映射到内部surname
字段。