当前位置: 首页 > wzjs >正文

安徽政务服务网佛山seo优化

安徽政务服务网,佛山seo优化,内蒙古建设工程交易中心网站,做网站用c语言吗问题描述 业务需要调用一个第三方图像识别的API,然后将识别出来的结果区分出不同类型,并分别装配到对应的Java实体类里 听起来是一个很正常的需求,现在JSON解析的工具有很多,而且都很成熟,但奈何识别出的JSON结果嵌套…

问题描述

业务需要调用一个第三方图像识别的API,然后将识别出来的结果区分出不同类型,并分别装配到对应的Java实体类里

听起来是一个很正常的需求,现在JSON解析的工具有很多,而且都很成熟,但奈何识别出的JSON结果嵌套了很多复杂的结构,找不到现成的工具方法解决这个问题,JSON格式如下所示:

{"words_result": [{"result": {"AmountInWords": [{"word": "贰佰圆整"}],"InvoiceNumConfirm": [{"word": "8xxxxx13"}],// ================================省略n行// ****************************************"CommodityPrice": [{"row": "1","word": "7.1238475"}],"CommodityNum": [{"row": "1","word": "24.8447205"}],"CommodityTaxRate": [{"row": "1","word": "13%"}],"InvoiceCode": [{"word": "0xxxxx611"}],"AmountInFiguers": [{"word": "200.00"}],"CommodityAmount": [{"row": "1","word": "176.99"}],"CommodityType": [{"row": "1","word": "92号"}],"CommodityTax": [{"row": "1","word": "23.01"}],"CommodityUnit": [{"row": "1","word": "升"}],"CommodityName": [{"row": "1","word": "*汽油*92号车用汽油(VIB)"}],"InvoiceNum": [{"word": "8xxxxx3"}]},"top": 0,"left": 0,"probability": 0.9595113397,"width": 845,"type": "vat_invoice","height": 544}],"words_result_num": 1,"pdf_file_size": 1,"log_id": "1xxxxxxxxxxxx8"
}

因此我需要手动设计JSON解析的方法

问题分析

因为需要根据不同的识别结果种类,装配到不同的实体类中,并且可能会灵活增加或删除种类,所以需要设计一套易于拓展,方便开发的的方案

根据这样的业务场景,我决定使用工厂模式的策略模式来实现,创建一个总的接口类,子类都实现该接口类,并且使用Java的反射机制,解析实体类的属性,和JSON识别结果的参数名进行一一查找对应,然后可以使用注解来标注类属性名和参数名的映射关系

这样可以实现通用的,易于拓展的代码,需要改变参数值或增加减少识别种类,只需要改变实体类属性本身,不需要改变装配代码

(原JSON中参数名下带"row"字段的,需要额外放到实体类下货品类数组中,row代表第几行的index,和实体类本身是父子关系)

问题解决

接口枚举类样例
// 接口类
public interface Invoice {String getInvoiceNum();String getAmount();
}// 字段映射注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InvoiceJsonField {String value();
}// 识别种类枚举
public enum InvoiceTypeEnum {VAT_INVOICE("vat_invoice"),TICKET_INVOICE("ticket_invoice");private String typeCode;InvoiceTypeEnum(String typeCode) {this.typeCode = typeCode;}public String getTypeCode() {return typeCode;}public void setTypeCode(String typeCode) {this.typeCode = typeCode;}
}
实体类样例
// 实体类种类1-实现接口Invoice
@Data
public class VatInvoice implements Invoice {private String invoiceNum;private String invoiceCode;private List<CommodityInfo> commodityList;  // 货品list// 属性名与参数名不一致,同注解写明映射关系@InvoiceJsonField("AmountInFiguers")private String amount;private String amountInWords;
}// 实体类种类2-实现接口Invoice
@Data
public class TicketInvoice implements Invoice {@InvoiceJsonField("ticketNum")private String invoiceNum;private String invoiceName;@InvoiceJsonField("AmountInFiguers")private String ticketAmount;private String amountInWords;
}// 货品类,JSON中带"row"字段的属性,row代表第几行的index
@Data
public class CommodityInfo implements Serializable {@InvoiceJsonField("commodityName")private String name; //货物名称@InvoiceJsonField("commodityType")private String type;//规格型号@InvoiceJsonField("commodityUnit")private String unit;//单位@InvoiceJsonField("commodityNum")private String num;//数量@InvoiceJsonField("commodityPrice")private String price;//单价@InvoiceJsonField("commodityAmount")private String amount;//金额@InvoiceJsonField("commodityTaxRate")private String taxRate;//税率@InvoiceJsonField("commodityTax")private String tax;//税额
}
工厂类

parseInvoice() 方法构造目标对象

public class InvoiceFactory {public static Invoice parseInvoice(JSONObject resObject) throws JsonProcessingException, IllegalAccessException {ObjectMapper objectMapper = new ObjectMapper();JsonNode rootNode = objectMapper.readTree(resObject.toString());String type = rootNode.get("words_result").get(0).get("type").asText();JsonNode wordsResultNode = rootNode.get("words_result").get(0).get("result");Invoice invoice;Boolean isCommodity = false;if (type.equals(InvoiceTypeEnum.VAT_INVOICE.getTypeCode())){invoice = new VatInvoice();isCommodity = true;}else if (type.equals(InvoiceTypeEnum.TICKET_INVOICE.getTypeCode())){invoice = new TicketInvoice();}else{//===加新的类只需要在这加,类实现Invoice接口,添加枚举种类,类属性名和接口返回值属性名一致,驼峰命名首字母小写============throw new RuntimeException();  // 可改为自定义异常抛错}return parseInvoice(invoice, wordsResultNode,isCommodity);}private static Invoice parseInvoice(Invoice invoice, JsonNode wordsResultNode, Boolean isCommodity) throws IllegalAccessException {List<CommodityInfo> infoList = new ArrayList<>();// 反射机制-解析类Class<?> clazz = invoice.getClass();Field[] fields = clazz.getDeclaredFields();Iterator<Map.Entry<String, JsonNode>> fieldsIterator = wordsResultNode.fields();while (fieldsIterator.hasNext()) {// 遍历参数与实体类Map.Entry<String, JsonNode> jsonField = fieldsIterator.next();String jsonKey = jsonField.getKey();JsonNode jsonValue = jsonField.getValue();String javaFieldName = toLowerCaseCamelCase(jsonKey);if (isCommodity){// 装配List<CommodityInfo>setCommodity(infoList,javaFieldName,jsonValue);}// 装配一般字段setFieldValueFor(fields, invoice, jsonValue, javaFieldName);}if (isCommodity){for (Field field : fields) {if (field.getName().equals("commodityList")){field.setAccessible(true);field.set(invoice,infoList);}}}return invoice;}// 装配List<CommodityInfo>private static void setCommodity(List<CommodityInfo> commodity,String javaFieldName,JsonNode jsonValue){JsonNode jsonNode = jsonValue.get(0);if(jsonNode != null && jsonNode.get("row") != null){Integer index = jsonNode.get("row").asInt() - 1;if (commodity.size()<index+1){CommodityInfo commodityInfo = new CommodityInfo();setFieldValueFor(CommodityInfo.class.getDeclaredFields(),commodityInfo,jsonNode,javaFieldName);commodity.add(index,commodityInfo);}else{setFieldValueFor(CommodityInfo.class.getDeclaredFields(),commodity.get(index),jsonNode,javaFieldName);}}}// 属性名驼峰转换private static String toLowerCaseCamelCase(String str) {if (str == null || str.isEmpty()) {return str;}StringBuilder result = new StringBuilder();boolean capitalizeNext = false;for (char c : str.toCharArray()) {if (c == '_') {capitalizeNext = true;} else {if (capitalizeNext) {result.append(Character.toUpperCase(c));capitalizeNext = false;} else {result.append(c);}}}str = result.toString();return Character.toLowerCase(str.charAt(0)) + str.substring(1);}// 反射机制给实体类set值private static void setFieldValueFor(Field[] fields, Object object, JsonNode jsonValue, String jsonFieldName) {for (Field field : fields) {InvoiceJsonField annotation = field.getAnnotation(InvoiceJsonField.class);// 如果有注解映射关系,优先寻找,没有则默认按属性名走boolean shouldMap = (annotation != null && toLowerCaseCamelCase(annotation.value()).equals(jsonFieldName)) ||(annotation == null && field.getName().equals(jsonFieldName));if (shouldMap) {try {// 设置字段值Object value = parseFieldValue(field.getType(), jsonValue);field.setAccessible(true);if (value.getClass().isAssignableFrom(String.class)){field.set(object, value);}else{field.set(object, ((TextNode)value).textValue());}} catch (IllegalAccessException e) {e.printStackTrace();}}}}// 设置字段值private static Object parseFieldValue(Class<?> fieldType, JsonNode jsonValue) {if (jsonValue == null || jsonValue.isNull()) {return null;}// 去掉word这一层级,手动放值if (fieldType.isArray()) {ArrayNode arrayNode = (ArrayNode) jsonValue;List<String> list = new ArrayList<>();for (JsonNode item : arrayNode) {list.add(String.valueOf(item.get("word").asText()));}return list.toArray(new String[0]);}if (fieldType.isAssignableFrom(String.class)) {if (jsonValue.get("word")!=null){return jsonValue.get("word").asText();}else{ArrayNode arrayNode = (ArrayNode) jsonValue;String builder = "";if (arrayNode.isEmpty()){return "";}else{builder = builder + arrayNode.get(0).get("word").asText();for (int i = 1; i < arrayNode.size(); i++) {builder = builder + ",";builder = builder + arrayNode.get(i).get("word").asText();}}return builder.toString();}}return null;}}

结果测试

对于问题描述中给出的识别JSON样例,进行解析测试

public class Main {// 测试demopublic static void main(String[] args) {String testJson = "..........";		// 省略jsontry {Invoice invoice = InvoiceFactory.parseInvoice(JSONObject.parseObject(testJson));System.out.println(invoice);} catch (JsonProcessingException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}
}

测试打印结果,可以看到属性值都已经正确放到实体类中了

VatInvoice(invoiceNum=8xxxxx3, invoiceCode=0xxxxx611, commodityList=[CommodityInfo(name=*汽油*92号车用汽油(VIB), type=92, unit=, num=24.8447205, price=7.1238475, amount=176.99, taxRate=13%, tax=23.01)], amount=200.00, amountInWords=贰佰圆整)
http://www.dtcms.com/wzjs/555177.html

相关文章:

  • 网站搭建公司排名现在给别人做网站
  • 东莞品牌网站建设服务网站开发程序员的工资是多少
  • 上海公司网站建设公司企业年金
  • 宿迁高端网站建设燕郊 网站开发
  • 有没有专门做蛋糕的网站永久免费国外域名注册
  • 企业建网站平台wordpress特别版
  • php网站建设 关键技术做微商有卖鞋子的网站吗
  • wap网站建设案例企业网站设计专业好吗
  • 深圳公明做网站系统开发需求文档
  • 钢结构人才网seo短视频保密路线
  • 网站安全评估报告私密性最好的浏览器
  • 威海做网站优化大学生创业计划书完整版
  • 齐齐哈尔网站开发绍兴网站建设公司哪家专业
  • 平台网站模板素材广州建站模板平台
  • 网站域名价格网页推广软件哪个好
  • 找回老网站深圳o2o网站建设
  • 山东省乡镇网站建设wordpress 简洁博客
  • 网站内链结构是什么意思公司网页制作哪家强
  • 网站项目上线流程连江厦门网站建设公司
  • 网站 技术seo排名软件价格
  • 桐乡做网站的公司做营销型网站服务
  • iis建设个人网站网站开发网站排名优化
  • 网站建设现状怎么做网站推广怎么样
  • 免费自助小型网站wordpress edu 2.0
  • 网站图片一般的像素湘潭做网站 磐石网络很专业
  • 遵义网站开发wordpress 插件 简码
  • 漯河英文网站建设html网站完整代码
  • jsp做就业网站郑州七彩网站建设公司
  • 福州网站关键词在线个人网站
  • 南京企业网站开发公司世代网络高端企业网站建设设计功能公司