使用Jackson解析动态生成的JSON对象名称

时间:2014-01-06 01:40:25

标签: java json jackson

我正在尝试使用Jackson将一些MediaWiki上下文从JSON反序列化为POJO。但是,问题是其中一个JSON对象名是文章的整数ID值,因此不能使用类似@JsonProperty的注释,因为该值永远不会是常量。

这里有一些示例JSON来描述我的意思:

http://en.wikipedia.org/w/api.php?action=query&titles=Albert%20Einstein&prop=info&format=json&indexpageids

{
    "query": {
        "pageids": [
            "736"
        ],
        "pages": {
            "736": {
                "pageid": 736,
                "ns": 0,
                "title": "Albert Einstein",
                "contentmodel": "wikitext",
                "pagelanguage": "en",
                "touched": "2014-01-05T03:14:23Z",
                "lastrevid": 588780054,
                "counter": "",
                "length": 106159
            }
        }
    }
}

(MediaWiki建议添加& indexpageids参数来帮助解析,但我看不出它对我有用。)

我也尝试使用@JsonAnyGetter@JsonAnySetter注释,但它们似乎没有帮助,抛出相同的异常com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "736" (class WikipediaPages), not marked as ignorable (one known property: "wikipediaPage"])

感谢您提供的任何帮助。

编辑:以下是相关课程的内容:

public class WikipediaPages {

    private Map<String, WikipediaPage> wikipediaPageMap = new HashMap<String, WikipediaPage>();

    public Map<String, WikipediaPage> getWikipediaPageMap() {
        return wikipediaPageMap;
    }

    public void setWikipediaPageMap(Map<String, WikipediaPage> wikipediaPageMap) {
        this.wikipediaPageMap = wikipediaPageMap;
    }
}

我使用Jackson Mixin来应用注释:

public interface WikipediaPagesMixIn {

    @JsonAnyGetter
    Map<String, WikipediaPage> getWikipediaPageMap();

    @JsonAnySetter
    void setWikipediaPageMap(Map<String, WikipediaPage> wikipediaPageMap);
}

编辑2:根据要求提供更多代码:

public class JacksonBuilder {

    private static ObjectMapper objectMapper;

    public static ObjectMapper getObjectMapper() {
        if(objectMapper == null) {
            objectMapper = new ObjectMapper();
            objectMapper.registerModule(new WikipediaModule());
        }

        return objectMapper;
    }
}

public class WikipediaModule extends SimpleModule {

    public WikipediaModule() {
        super("WikipediaModule", new Version(1, 0, 0, null, "net.ryanmorrison", "sentience"));
    }

    @Override
    public void setupModule(SetupContext setupContext) {
        setupContext.setMixInAnnotations(WikipediaPage.class, WikipediaPageMixIn.class);
        setupContext.setMixInAnnotations(WikipediaPages.class, WikipediaPagesMixIn.class);
        setupContext.setMixInAnnotations(WikipediaQuery.class, WikipediaQueryMixIn.class);
        setupContext.setMixInAnnotations(WikipediaResult.class, WikipediaResultMixIn.class);
    }
}

public class WikipediaResult {

    private WikipediaQuery wikipediaQuery;

    public WikipediaQuery getWikipediaQuery() {
        return wikipediaQuery;
    }

    public void setWikipediaQuery(WikipediaQuery wikipediaQuery) {
        this.wikipediaQuery = wikipediaQuery;
    }
}

public interface WikipediaResultMixIn {

    @JsonProperty("query")
    WikipediaQuery getWikipediaQuery();
}

1 个答案:

答案 0 :(得分:2)

要回答异常的根本原因,@JsonAnySetter javadoc状态

  

可用于定义非静态的标记注释,   双参数方法(属性的第一个参数名称,第二个值为   设置),[...]

因此,使用像这样的mixin

@JsonAnySetter
void setWikipediaPageMap(Map<String, WikipediaPage> wikipediaPageMap);

未注册,因此找不到该属性。

老实说,如果您控制数据类,请不要使用mixins。您可以直接映射字段,如下所示。


我不知道你是如何使用mixin的,但下面的内容适用于我

String json = "{ \"query\": { \"pageids\": [ \"736\" ], \"pages\": { \"736\": { \"pageid\": 736, \"ns\": 0, \"title\": \"Albert Einstein\", \"contentmodel\": \"wikitext\", \"pagelanguage\": \"en\", \"touched\": \"2014-01-05T03:14:23Z\", \"lastrevid\": 588780054, \"counter\": \"\", \"length\": 106159 } } } }";
ObjectMapper mapper = new ObjectMapper();
JsonNode node =mapper.readTree(json);

node = node.get("query").get("pages");

Map<String, Page> pages = mapper.readValue(node.traverse(), new TypeReference<Map<String, Page>>() {
});

System.out.println(pages);

打印

{736=Page [pageid=736, ns=0, title=Albert Einstein, contentmodel=wikitext, pagelanguage=en, touched=2014-01-05T03:14:23Z, lastrevid=588780054, counter=, length=106159]}

Page

的位置
class Page {
    private int pageid;
    private int ns;
    private String title;
    private String contentmodel;
    private String pagelanguage;
    private String touched; // this could be a Date, with the appropriate format configuration
    private int lastrevid;
    private String counter;
    private int length;
    @Override
    public String toString() {
        return "Page [pageid=" + pageid + ", ns=" + ns + ", title=" + title
                + ", contentmodel=" + contentmodel + ", pagelanguage="
                + pagelanguage + ", touched=" + touched + ", lastrevid="
                + lastrevid + ", counter=" + counter + ", length=" + length
                + "]";
    }
    public int getPageid() {
        return pageid;
    }
    public void setPageid(int pageid) {
        this.pageid = pageid;
    }
    public int getNs() {
        return ns;
    }
    public void setNs(int ns) {
        this.ns = ns;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getContentmodel() {
        return contentmodel;
    }
    public void setContentmodel(String contentmodel) {
        this.contentmodel = contentmodel;
    }
    public String getPagelanguage() {
        return pagelanguage;
    }
    public void setPagelanguage(String pagelanguage) {
        this.pagelanguage = pagelanguage;
    }
    public String getTouched() {
        return touched;
    }
    public void setTouched(String touched) {
        this.touched = touched;
    }
    public int getLastrevid() {
        return lastrevid;
    }
    public void setLastrevid(int lastrevid) {
        this.lastrevid = lastrevid;
    }
    public String getCounter() {
        return counter;
    }
    public void setCounter(String counter) {
        this.counter = counter;
    }
    public int getLength() {
        return length;
    }
    public void setLength(int length) {
        this.length = length;
    }
}

剩下的就是将Map<String, Page>作为字段放在querypages JSON元素的某个包装类中。