将杰克逊的不同领域变成一个变量

时间:2015-02-13 07:36:52

标签: java json jackson

我遇到了与杰克逊对象去除物品的问题。问题是,在我收到的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()]);
    }
}

解决方案看起来很难看但有效。以太,如果有人能给我一个更好的解决方案,我会接受这个答案。感谢。

1 个答案:

答案 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字段。