概要
統一された標準がない場合、システムが複数の外部システムに接続すると、異種のリクエスト インターフェイスの応答データが返されることがよくあります。 、または
JSON を返す場合があります。戻り値の型が異なるだけでなく、コンテンツの構造も異なります。 XML タイプを例にとると、
インターフェース 1 はコンテンツを返します
<root>
<bizKey>16112638767472747178067</bizKey>
<returnMsg>OK</returnMsg>
<returnCode>200</returnCode>
...
</root>
ログイン後にコピー
インターフェース 2 はコンテンツを返します
<root>
<bid>16112638767472747178068</bid>
<note>成功</note>
<returnStatus>1</returnStatus>
...
</root>
ログイン後にコピー
上記のコンテンツでは、3 種類の情報のみを考慮しています。 、それぞれビジネス ID、ステータス値、説明情報です。この 3 種類の情報を取得した後、ビジネス ロジック処理を実行できますか?
XML と JSON の解析
ビジネス抽象化に従って、XML または JSON コンテンツから 3 種類の情報を取得する必要があります。ここでは
XPath
と JSONPath を使用して解析します。たとえば、インターフェイス 1 に関する重要な情報を取得するには、{
bid: "/root/bizKey",
code: "/root/returnCode",
description: "/root/returnMsg"
}
ログイン後にコピー
bid
、code
、および description
という 3 つの XPath 式を設定できます。 us システム自体によって定義されたフィールド名。
JSONPath 式が定義されていることを除いて、JSON コンテンツの解析にも同じことが当てはまります。
データ コンテンツを 2 つのステップで処理しますbid
,code
和description
对应我们系统自己定义的字段名。
解析JSON内容也是同理的,只不过定义的是JSONPath表达式。
分两步走处理数据内容
假设我们从原始的XML和JSON数据中获得了bid
,code
和description
信息,
从接口1获得
{
bid: '16112638767472747178067',
code: '200',
description: 'OK'
}
ログイン後にコピー
从接口2获得
{
bid: '16112638767472747178068',
code: '1',
description: '成功'
}
ログイン後にコピー
假设我们从接口1文档获知状态值200
表示请求成功,从接口2文档获知状态值1
元の XML および JSON データから bid
、code
、および description
情報を取得するとします。インターフェース 1 から取得
public class XmlParseUtils {
private DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
private XPathFactory xpathFactory = XPathFactory.newInstance();
/**
*
* @param param 数据内容
* @param paths 表达式
* @return
* @throws Exception
*/
public Map<String,Object> parse(String param, Map<String,String> paths) throws Exception{
InputSource inputSource = new InputSource(new StringReader(param));
Document document = dbFactory.newDocumentBuilder().parse(inputSource);
Map<String,Object> map = Maps.newHashMap();
for(String key : paths.keySet()) {
XPath xpath = xpathFactory.newXPath();
Node node = (Node) xpath.evaluate(paths.get(key), document, XPathConstants.NODE);
if(node == null) {
throw new Exception("node not found, xpath is " + paths.get(key));
}
map.put(key, node.getTextContent());
}
return map;
}
}
ログイン後にコピー
ログイン後にコピー
インターフェース 2 から取得
code.equals("200") ? 2: 3
ログイン後にコピー
ログイン後にコピー
インターフェース 1 のドキュメントからステータス値 200
を取得するとします。これはリクエストが成功したことを意味し、ステータス値 1 を取得するとします。インターフェイス 2 ドキュメント コードの </> は、リクエストが成功したことを示していますが、これらはすべてリクエストが成功したことを示していますが、ビジネス関連のテーブルにそのまま保存することはできません (もちろん、これらの応答データは保存する必要があります)。少なくともトラブルシューティングを容易にするために、別のレコード テーブルに保存します。 <tr class="firstRow">ビジネス関連のテーブルが次のように設計されているとします<th align="left"></th><th align="right"></th><th align="left">フィールド名</th></tr>タイプ</thead><tbody>説明<tr><td align="left"></td><td align="right"></td><td align="left">入札</td></tr>文字列<tr><td align="left">ビジネスID</td><td align="right"></td><td align="left">コード</td> </tr>int<tr><td align="left">ステータス値 、 0=初期、1=要求中、2=成功、3=失敗</td><td align="right"></td><td align="left">説明</td></tr>文字列</tbody></table>説明🎜🎜🎜🎜<p>因此,我们还必须定义规则把接口1返回的状态值<code>200
转换为我们系统的2
,把接口2返回的状态值1
转换为我们系统的2
。
总结一下,两步走解析XML和JSON数据内容根据XPath或者JSONPath表达式解析获得重要信息
根据规则转换状态值
第一步解析数据获得重要信息
以XML为例,
public class XmlParseUtils {
private DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
private XPathFactory xpathFactory = XPathFactory.newInstance();
/**
*
* @param param 数据内容
* @param paths 表达式
* @return
* @throws Exception
*/
public Map<String,Object> parse(String param, Map<String,String> paths) throws Exception{
InputSource inputSource = new InputSource(new StringReader(param));
Document document = dbFactory.newDocumentBuilder().parse(inputSource);
Map<String,Object> map = Maps.newHashMap();
for(String key : paths.keySet()) {
XPath xpath = xpathFactory.newXPath();
Node node = (Node) xpath.evaluate(paths.get(key), document, XPathConstants.NODE);
if(node == null) {
throw new Exception("node not found, xpath is " + paths.get(key));
}
map.put(key, node.getTextContent());
}
return map;
}
}
ログイン後にコピー
ログイン後にコピー
parse
函数的返回类型也可以是Map<String,String>
,暂且用Map<String,Object>
。
第二步根据规则转换状态值
这一步稍稍有点麻烦,不过我们先不考虑代码实现,反正你能想到的可能别人已经帮你实现了。首先我们根据接口文档定义规则,写出规则表达式(或者其他的什么),
又是表达式。假设接口1的返回的状态值比较简单,只有200
表示成功,其他情况都是失败,那么我们可以这样定义规则,
code.equals("200") ? 2: 3
ログイン後にコピー
ログイン後にコピー
或者
<#if code == "200">
2
<#else>
3
<#/if>
ログイン後にコピー
ログイン後にコピー
亦或者
function handle(arg) {
if(arg == 200) {
return 2;
}
return 3;
}
handle(${code})
ログイン後にコピー
以上根据同一份文档定义了三种不同类型的状态值转换规则,肯定需要三种不同的实现。下面一一说明,
三目表达式
code.equals("200") ? 2: 3
是一个三目表达式,我们将使用jexl
引擎来解析,利用第一步解析数据获得重要信息的结果,我们可以这样做
public Object evaluateByJexl(String expression, Map<String,Object> context) {
JexlEngine jexl = new JexlBuilder().create();
JexlExpression e = jexl.createExpression(expression);
JexlContext jc = new MapContext(context);
return e.evaluate(jc);
}
ログイン後にコピー
FreeMarker模板
<#if code == "200">
2
<#else>
3
<#/if>
ログイン後にコピー
ログイン後にコピー
处理这段模板我们可以这么做
/**
*
* @param param FreeMarker模板
* @param context
* @return
* @throws Exception
*/
public String render(String param, Map<String,Object> context) throws Exception {
Configuration cfg = new Configuration();
StringTemplateLoader stringLoader = new StringTemplateLoader();
stringLoader.putTemplate("myTemplate",param);
cfg.setTemplateLoader(stringLoader);
Template template = cfg.getTemplate("myTemplate","utf-8");
StringWriter writer = new StringWriter();
template.process(context, writer);
return writer.toString();
}
ログイン後にコピー
如果FreeMarker
模板比较复杂,从模板预编译成Template
可能会消耗更多的性能,就要考虑把Template
缓存起来。
JavaScript代码段
function handle(arg) {
if(arg == 200) {
return 2;
}
return 3;
}
handle(${code})
ログイン後にコピー
这段js
代码中存在${code}
,首先它需要使用FreeMarker
渲染得到真正的handle
方法的调用参数,然后
public Object evaluate(String expression) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("javascript");
return engine.eval(expression);
}
ログイン後にコピー
ScriptEngineManager
的性能估计不太乐观,毕竟是一个语言的引擎。
不同转换规则实现的比较
类型 | 实现 | 优点 | 缺点 |
---|
三目表达式 | Jexl | 简单(easy) | 简单(simple) |
FreeMarker模板 | FreeMarker | -- | -- |
JavaScript代码段 | FreeMarker + ScriptEngine | 直观 | 过程复杂,性能问题 |
看起来Freemarker
是一个不错的选择。
至此两步走小技巧已经实现了,都是利用了现成的代码实现。
或许我们会这样的挑战,在做状态值转换时需要知道当前系统某个业务状态值的情况,
此时Freemarker
表达式可能是这样的,
<# assign lastCode = GetLastCode(code)>
<#if lastCode == "2">
2
<#elseif code == "200">
2
<#else>
3
<#/if>
ログイン後にコピー
这里我们可以使用Freemarker的特性,自定义Java函数或工具类,在模板中调用。
以上がXML および JSON コンテンツを解析するためのいくつかの手法のコード共有例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
-
2023-03-15 16:54:01
-
2023-03-15 12:26:02
-
2023-03-14 18:58:01
-
2023-03-14 11:30:01
-
1970-01-01 08:00:00
-
2023-03-16 15:20:01
-
1970-01-01 08:00:00
-
1970-01-01 08:00:00
-
1970-01-01 08:00:00
-
1970-01-01 08:00:00