栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

使用Jackson从JSON获取单个字段

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用Jackson从JSON获取单个字段

Jackson之路

考虑到您没有描述数据结构的POJO,可以简单地执行以下操作:

final String json = "{"contentType": "foo", "fooField1": ... }";final ObjectNode node = new ObjectMapper().readValue(json, ObjectNode.class);//        ^ // actually, try and *reuse* a single instance of ObjectMapperif (node.has("contentType")) {    System.out.println("contentType: " + node.get("contentType"));}

解决评论部分中的问题

但是,如果您不希望消耗整个源

String
,而只是访问其路径已知的特定属性,则必须使用Tokeniser自己编写。


实际上,这是周末,我有时间在手上,所以我可以给您一个良好的开端:这是一个基本的开始!它可以在

strict
模式下运行并发出明智的错误消息,或者宽容并
Optional.empty
在无法满足请求时返回。

public static class JSonPath {    protected static final JsonFactory JSON_FACTORY = new JsonFactory();    private final List<JSONKey> keys;    public JSonPath(final String from) {        this.keys = Arrays.stream((from.startsWith("[") ? from : String.valueOf("." + from))     .split("(?=\[|\]|\.)"))     .filter(x -> !"]".equals(x))     .map(JSONKey::new)     .collect(Collectors.toList());    }    public Optional<String> getWithin(final String json) throws IOException {        return this.getWithin(json, false);    }    public Optional<String> getWithin(final String json, final boolean strict) throws IOException {        try (final InputStream stream = new StringInputStream(json)) { return this.getWithin(stream, strict);        }    }    public Optional<String> getWithin(final InputStream json) throws IOException {        return this.getWithin(json, false);    }    public Optional<String> getWithin(final InputStream json, final boolean strict) throws IOException {        return getValueAt(JSON_FACTORY.createParser(json), 0, strict);    }    protected Optional<String> getValueAt(final JsonParser parser, final int idx, final boolean strict) throws IOException {        try { if (parser.isClosed()) {     return Optional.empty(); } if (idx >= this.keys.size()) {     parser.nextToken();     if (null == parser.getValueAsString()) {         throw new JSonPathException("The selected node is not a leaf");     }     return Optional.of(parser.getValueAsString()); } this.keys.get(idx).advanceCursor(parser); return getValueAt(parser, idx + 1, strict);        } catch (final JSonPathException e) { if (strict) {     throw (null == e.getCause() ? new JSonPathException(e.getMessage() + String.format(", at path: '%s'", this.toString(idx)), e) : e); } return Optional.empty();        }    }    @Override    public String toString() {        return ((Function<String, String>) x -> x.startsWith(".") ? x.substring(1) : x)     .apply(this.keys.stream().map(JSONKey::toString).collect(Collectors.joining()));    }    private String toString(final int idx) {        return ((Function<String, String>) x -> x.startsWith(".") ? x.substring(1) : x)     .apply(this.keys.subList(0, idx).stream().map(JSONKey::toString).collect(Collectors.joining()));    }    @SuppressWarnings("serial")    public static class JSonPathException extends RuntimeException {        public JSonPathException() { super();        }        public JSonPathException(final String message) { super(message);        }        public JSonPathException(final String message, final Throwable cause) { super(message, cause);        }        public JSonPathException(final Throwable cause) { super(cause);        }    }    private static class JSonKey {        private final String key;        private final JsonToken startToken;        public JSonKey(final String str) { this(str.substring(1), str.startsWith("[") ? JsonToken.START_ARRAY : JsonToken.START_OBJECT);        }        private JSonKey(final String key, final JsonToken startToken) { this.key = key; this.startToken = startToken;        }                public void advanceCursor(final JsonParser parser) throws IOException { final JsonToken token = parser.nextToken(); if (!this.startToken.equals(token)) {     throw new JSonPathException(String.format("Expected token of type '%s', got: '%s'", this.startToken, token)); } if (JsonToken.START_ARRAY.equals(this.startToken)) {     // Moving cursor within a JSON Array     for (int i = 0; i != Integer.valueOf(this.key).intValue(); i++) {         JSONKey.skipTonext(parser);     } } else {     // Moving cursor in a JSON Object     String name;     for (parser.nextToken(), name = parser.getCurrentName(); !this.key.equals(name); parser.nextToken(), name = parser.getCurrentName()) {         JSONKey.skipTonext(parser);     } }        }                private static void skipTonext(final JsonParser parser) throws IOException { final JsonToken token = parser.nextToken(); if (JsonToken.START_ARRAY.equals(token) || JsonToken.START_OBJECT.equals(token) || JsonToken.FIELD_NAME.equals(token)) {     skipTonextImpl(parser, 1); } else if (JsonToken.END_ARRAY.equals(token) || JsonToken.END_OBJECT.equals(token)) {     throw new JSonPathException("Could not find requested key"); }        }                private static void skipTonextImpl(final JsonParser parser, final int depth) throws IOException { if (depth == 0) {     return; } final JsonToken token = parser.nextToken(); if (JsonToken.START_ARRAY.equals(token) || JsonToken.START_OBJECT.equals(token) || JsonToken.FIELD_NAME.equals(token)) {     skipTonextImpl(parser, depth + 1); } else {     skipTonextImpl(parser, depth - 1); }        }        @Override        public String toString() { return String.format(this.startToken.equals(JsonToken.START_ARRAY) ? "[%s]" : ".%s", this.key);        }    }}

假设以下JSON内容:

{  "people": [{    "name": "Eric",    "age": 28  }, {    "name": "Karin",    "age": 26  }],  "company": {    "name": "Elm Farm",    "address": "3756 Preston Street Wichita, KS 67213",    "phone": "857-778-1265"  }}

…您可以

JSONPath
按如下方式使用我的课程:

    final String json = "{"people":[],"company":{}}"; // refer to JSON above    System.out.println(new JSonPath("people[0].name").getWithin(json)); // Optional[Eric]    System.out.println(new JSonPath("people[1].name").getWithin(json)); // Optional[Karin]    System.out.println(new JSonPath("people[2].name").getWithin(json)); // Optional.empty    System.out.println(new JSonPath("people[0].age").getWithin(json));  // Optional[28]    System.out.println(new JSonPath("company").getWithin(json));        // Optional.empty    System.out.println(new JSonPath("company.name").getWithin(json));   // Optional[Elm Farm]

请记住,这是 基本的 。它不强制数据类型(返回的每个值都是

String
),仅返回叶节点。

实际测试案例

它处理

InputStream
s,因此您可以针对一些巨大的JSON文档进行测试,并发现它比浏览器下载并显示其内容要快得多:

System.out.println(new JSonPath("info.contact.email") .getWithin(new URL("http://test-api.rescuegroups.org/v5/public/swagger.php").openStream()));// Optional[support@rescuegroups.org]

快速测试

请注意,我没有重用任何现有的,

JSONPath
否则
ObjectMapper
结果是不准确的-无论如何,这只是一个非常粗略的比较:

public static Long time(final Callable<?> r) throws Exception {    final long start = System.currentTimeMillis();    r.call();    return Long.valueOf(System.currentTimeMillis() - start);}public static void main(final String[] args) throws Exception {    final URL url = new URL("http://test-api.rescuegroups.org/v5/public/swagger.php");    System.out.println(String.format(   "%dms to get 'info.contact.email' with JSONPath",       time(() -> new JSonPath("info.contact.email").getWithin(url.openStream()))));    System.out.println(String.format(   "%dms to just download the entire document otherwise",       time(() -> new Scanner(url.openStream()).useDelimiter("\A").next())));    System.out.println(String.format(   "%dms to bluntly map it entirely with Jackson and access a specific field",       time(() -> new ObjectMapper()    .readValue(url.openStream(), ObjectNode.class)    .get("info").get("contact").get("email"))));}

378ms即可使用JSONPath获得“ info.contact.email”
756ms即可下载整个文档,否则需要
896ms才能完全通过Jackson映射并访问特定字段



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/410083.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号