spring学习笔记---第三方SDK(Rest API)和Jaskson的巧用
前言:
其实我以前一直不懂电商, 以及电商中所涉及的业务概念. 对于SKU等名词, 觉得有些玄乎. 对其背后的数据模型, 也有莫名的未知恐惧感: 庞大而理不清头绪. 不过最近有机会接触了微商(有赞), 身体力行, 感觉加深了一些了解. 对之前一直谈到的店铺ISV, 也明白其的工作内容.
有赞(口袋通)做得真心的赞, 不过其java版的sdk, 始终觉得有些粗糙. 比如其返回结果是裸json字符串, 对于javaer而言, 习惯了pojo, 直接处理之还是显得有些麻烦, 因此我们需要在此基础上, 再做点额外的工作.
本篇文章, 将结合这个例子, 来讲解下jaskson的妙用.
相关文章:
一. Jackson的使用和定制.
这篇文章, 主要是服务端中, jackson库是如何扮演重要的角色. 本文是着重讲述, 在服务调用方, jackson是如何起到相应的作用的.
吐槽:
有赞API在线文档说明, 官方网址: http://open.koudaitong.com/doc.
JAVA版SDK的Sample样例分析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class KDTApiTest { private static final String APP_ID = "app_id" ; //这里换成你的app_id private static final String APP_SECRET = "app_secret" ; //这里换成你的app_secret /* * 测试获取单个商品信息 */ private static void sendGet(){ String method = "kdt.item.get" ; HashMap<String, String> params = new HashMap<String, String>(); params.put( "num_iid" , "2651514" ); KdtApiClient kdtApiClient; HttpResponse response; try { kdtApiClient = new KdtApiClient(APP_ID, APP_SECRET); response = kdtApiClient.get(method, params); System.out.println( "Response Code : " + response.getStatusLine().getStatusCode()); BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(response.getEntity().getContent())); StringBuffer result = new StringBuffer(); String line = "" ; while ((line = bufferedReader.readLine()) != null ) { result.append(line); } System.out.println(result.toString()); } catch (Exception e) { e.printStackTrace(); } } } |
从简单的sample代码中, 可以发现其ApiClient是对HttpClient做个一个简单的封装, 但封装并不彻底, 调用时和结果响应处理都有些麻烦.
我大致猜测其结果为何就返回一个json字符串, 让解析的工作留给平台开发者. 不是懒, 而是因为返回结果的变动可能性比较大, 不敢轻易定制为对应的POJO类对象.
返回的JSON字符串如下所示:
1 | { "response" :{ "item" :{ "cid" :5000000, "promotion_cid" :0, "tag_ids" : "58279885" , "skus" :[{ "num_iid" :105744782, "sku_id" :35872379, "sku_unique_code" : "10574478235872379" , "quantity" : "9999" , "outer_id" : "" }, ... |
注: 顶级元素为response, item对应具体的商品信息.
无论如何, json的解析工作, 还是省不了的, 那如何处理呢?
可以引入JSONObject, 按json字符串的层次结构来处理, 比如如下所示:
1 2 | JSONObject root = JSONObject.fromString(jsonText); JSONObject item = root.getJSONObject( "response" ).getJSONObject( "item" ); |
注: 这种编写方式, 非常的繁琐, 一点也不利于程序的快速处理, 那是否有利器来解决该问题呢? 我们的大英雄--jackson, 即将出马.
解决方案:
针对上述例子的kdt.item.get接口, 定义相应的POJO类.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @JsonIgnoreProperties (ignoreUnknown = true ) @JsonRootName ( "response" ) public class KdtItemGetResult { @JsonProperty ( "item" ) private GoodsDetailVO item; public GoodsDetailVO getItem() { return item; } public void setItem(GoodsDetailVO item) { this .item = item; } } |
注: POJO类, @JsonRootName可以设定Root元素, 用于剥离最外层, @JsonProperty用于设定对应json的key和属性的映射关系, @JsonIgnoreProperties(ignoreUnknown=true), 用于挑选需要的元素, 避开因为没有对应的pojo类属性而报错.
1 2 3 4 5 6 7 8 9 | @JsonIgnoreProperties (ignoreUnknown = true ) public class GoodsDetailVO { @JsonProperty ( "num_iid" ) private long numIid; @JsonProperty ( "alias" ) private String alias; @JsonProperty ( "title" ) private String title; } |
注: 其自然支持类层次结构的映射转换.
那么, 我们在继续修改下调用接口, 如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | public KdtItemGetResult kdtItemGet( long numIid) { String method = "kdt.item.get" ; HashMap<String, String> params = new HashMap<String, String>(); params.put( "num_iid" , "" + numIid); KdtApiClient kdtApiClient; HttpResponse response; try { kdtApiClient = new KdtApiClient(APP_ID, APP_SECRET); response = kdtApiClient.get(method, params); // System.out.println("Response Code : " + response.getStatusLine().getStatusCode()); BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(response.getEntity().getContent())); StringBuffer result = new StringBuffer(); String line = "" ; while ((line = bufferedReader.readLine()) != null ) { result.append(line); } System.out.println(result.toString()); String jsonText = result.toString(); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true ); KdtItemGetResult kigr = objectMapper.readValue(jsonText, KdtItemGetResult. class ); return kigr; } catch (Exception e) { // e.printStackTrace(); } return null ; } |
注: 除了请求的处理, 依旧如前, 但对json转换为pojo的处理, 变得非常的简洁.
其核心的代码就如下几句:
1 2 3 4 | ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true ); // 支持@JsonRootName的特性 KdtItemGetResult kigr = objectMapper.readValue(jsonText, KdtItemGetResult. class ); return kigr; |
当然rest api的调用, 有可能失败, 再在外层添加下TResult<T>的封装即可.
1 2 3 4 5 6 | public class TResult<T> { private boolean success = false ; private int errCode = 0 ; private String errMsg = "OK" ; private T value = null ; } |
如你所看到的, 封装处理就非常的方便, 借用一句广告词: 妈妈, 再也不用担心粗糙的第三方SDK了.
总结:
尽量让优秀的框架, 替你做繁琐的重复工作. 这是一个非常重要的提高工作效率的方式. 临近结笔, 发现写得虎头蛇尾, 权做笔记.
公众号&游戏站点:
个人微信公众号: 木目的H5游戏世界
posted on 2015-10-13 15:22 mumuxinfei 阅读(1761) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构