Kettle是一款国外开源的ETL工具,纯java编写,可以在Window、Linux、Unix上运行,数据抽取高效稳定。
但是本文重点不是讲Kettle安装和使用。
而是,如何使用Kettle处理Json文件,因为Kettle本身有一点点BUG,JsonInput不能直接处理Utf-8字符的json内容。
所以,要学会变通一下。本例子使用的Kettle版本为7.1,下载网址:https://sourceforge.net/projects/pentaho/files/Data%20Integration/7.1/pdi-ce-7.1.0.0-12.zip/download
首先,打开Kettle的图形编辑界面。
windows版本的命令为Spoon.bat。
看到这个界面说明你的Kettle环境没有问题。
然后点击菜单 文件->新建->转换
开始一个json文件的处理流程。
然后,从核心对象里面拖一个json Input对象出来。
如果json文件不是UTF-8的而是GBK,这样就可以处理了。但是本宝宝不是这样的。
所以,又变通一下,拖了两个组件。
一个是文件内容加载到内存,一个是文本文件输出。
这两个组件都有编码处理的选择项,这样宝宝就可以处理UTF-8的json文件了。
然后就是用连接线把三个组件串联起来,非常简单。
Json Input组件的一些参数是这样配置,当然JsonPath语法不是本文重点。
文件内容加载到内存的参数配置:
文本文件输出的参数配置:
都配置好了,就可以运行了。
然后,去看输出的结果文件。本例子输出了一个csv文件file2.csv。
内容如下:
f2,f3,f4
"{""总分"":0,""rcAppId"":""a637725d-aabb-41e3-8128-713dd06f0b76"",""结果"":""拒绝"",""备注"":""征信不良记录"",""费率"":""0.009900""}",a637725d-aabb-41e3-8128-713dd06f0b76,征信不良记录
它是可以直接用Excel打开看的表格。
json源文件也贴上来。内容还是蛮复杂的,而且我还删减了部分内容。
{
"errorMessage": "",
"errorCode": "",
"responseData": {
"总分": 0,
"rcAppId": "a637725d-aabb-41e3-8128-713dd06f0b76",
"结果": "拒绝",
"备注": "征信不良记录",
"费率": "0.009900"
},
"持久化数据": {
"lastModifiedTime": "2018-03-30 15:49:06",
"bizDate": "2018-03-30",
"errorCode": "",
"productRcvId": 8,
"rawData": {
"request": {
"app": {
"minAmount": "5000.00",
"purpose": "经营",
"bizDate": "2018-03-30",
"accountFourVerification": false,
"agreeTime": 1522395949737,
"orgId": 3,
"isFirst": "false",
"appAmount": "5884.00",
"creditLine": "5884.00",
"rate": "0.009900",
"appId": "244d6d3d-2298-46ff-baaa-b252837585d7",
"accountNo": "未选择",
"isLine": "N",
"partyId": "5224f0bc-55cd-4e62-bbec-192990881660",
"maxAmount": "150000.00",
"loaTime": "20180330154445",
"period": 120,
"amount": "5884.00",
"loanUse": "经营",
"productId": "08363214-a832-4f64-bb80-be352d8d0f0f",
"externalId": "2",
"interestEnumId": 2011001,
"thruDate": 1837958400000,
"fromDate": 1522339200000,
"createBy": "13213571926",
"statusId": 200100,
"createTime": 1522395838000,
"tenantId": "71f28286-f5b3-40e5-ab2f-049b66328b1f"
},
"reference": {
"enterprise": {
"warmPromptMessage": "",
"businessLicenseCode": "123456789123456789",
"semiannualRevenue": "5282828",
"industryInvolved": "",
"isShow": true,
"creditCode": "",
"organizationCode": "",
"accountNo": false,
"name": "永嘉路",
"revenueDocumentId": ["b25ef019-29ed-4e6b-abb1-69667d3793e0"],
"businessPlaceType": "自有",
"annualRevenue": "",
"seq": 4
},
"frequentlyUsedAccount": {
"mobilePhone": "13213571926",
"accountNo": "6217370090101267356",
"fourVerification": false
},
"estate": {
"area": "36",
"isMortgage": false,
"purchaseDate": "",
"documentExplain": "",
"court": "盛世豪城小区",
"type": "住宅",
"structure": "",
"isLift": "电梯",
"toward": "",
"valuation": "108000",
"estateAddress": {
"address": "",
"province": "内蒙古",
"city": "巴彦淖尔",
"district": "临河区"
},
"isOwner": false,
"documentId": ["0ae9d39e-f7ee-44b8-a92e-cdff108401a9"],
"floor": ""
},
"asset": [],
"vehicle": {
"isMortgage": false,
"purchaseDate": "",
"engineNumber": "",
"documentExplain": "",
"type": "",
"plateNumber": "",
"isOwner": false,
"price": "",
"driverLicense": "",
"vin": "",
"documentId": [],
"brand": "",
"vehicleLicense": ""
}
},
"rcAppTypeCode": "2",
"tenantId": "71f28286-f5b3-40e5-ab2f-049b66328b1f",
"custPerson": {
"reservedCity": "巴彦淖尔",
"graduateSchool": "",
"weechatNo": "",
"education": "",
"contactInfo": [{
"workingUnit": "",
"twoVerification": false,
"weechatNo": "",
"mobilePhone": "13623895652",
"qqNo": "",
"name": "江大头",
"threeVerification": false,
"idNo": "410825198702245568",
"email": "",
"seq": 1,
"relation": "家人",
"isFrist": true
}, {
"workingUnit": "",
"twoVerification": false,
"weechatNo": "",
"mobilePhone": "13623895645",
"qqNo": "",
"name": "金城武张根硕",
"threeVerification": true,
"idNo": "15282319821014001X",
"email": "",
"seq": 2,
"relation": "配偶",
"isFrist": false
}, {
"workingUnit": "",
"twoVerification": false,
"weechatNo": "",
"mobilePhone": "13623895654",
"qqNo": "",
"name": "刘浩",
"threeVerification": false,
"idNo": "",
"email": "",
"seq": 3,
"relation": "同事",
"isFrist": false
}, {
"workingUnit": "",
"twoVerification": false,
"weechatNo": "",
"mobilePhone": "13623895651",
"qqNo": "",
"name": "江北",
"threeVerification": false,
"idNo": "",
"email": "",
"seq": 4,
"relation": "朋友",
"isFrist": false
}],
"gender": "",
"ethnicity": "",
"warmPromptMessage": "\n\t\t\t\t\t\t\n\t\t\t\t\t<p>温馨提示:</p><p>1.提供公户和密码。</p><p>2.社保局</p><p>3.社保局423</p>",
"idNo": "410326199804017527",
"permanentAddress": {
"address": "永嘉路",
"province": "内蒙古",
"city": "巴彦淖尔",
"district": "临河区"
},
"partyId": "5224f0bc-55cd-4e62-bbec-192990881660",
"formerName": "",
"email": "",
"seq": 1,
"identificationId": 1001,
"workingUnit": {
"occupation": "农、林、牧、渔、水利业生产人员",
"incomeProofDocumentId": ["9c4c086b-1bcd-483a-b8a3-fd34e178a48e"],
"unitNature": "国有企业",
"employmentDate": "",
"warmPromptMessage": "",
"companyName": "",
"averageIncome": "83839",
"unitSize": "",
"unitPhone": "",
"title": "中级领导",
"isShow": true,
"workingDate": "2018-03-19",
"afterTaxIncome": "939396",
"companyAddress": {
"address": "永嘉路",
"province": "内蒙古",
"city": "巴彦淖尔",
"district": "临河区"
},
"ptitle": "中级",
"workingEmail": "",
"companyIndustry": ""
},
"reservedFundsId": "134455",
"photoDocumentId": [],
"degree": "",
"health": "",
"isShow": true,
"creditBalance": "63044.00",
"graduateDate": "",
"reservedFunds": {
"password": "34566",
"city": "巴彦淖尔",
"username": "134455"
},
"qqNo": "",
"mobilePhone": "13213571926",
"mateThreeVerification": false,
"name": "常雨霖",
"firstThreeVerification": false,
"householdType": "",
"maritalStatus": "已婚",
"residenceAddress": {
"residenceType": "",
"address": "永嘉路",
"province": "内蒙古",
"telephoneNo": "",
"city": "巴彦淖尔",
"district": "临河"
},
"reservedFundsPassword": "34566",
"riskPreference": "1.00"
}
}
},
"tid": "71f28286-f5b3-40e5-ab2f-049b66328b1f",
"createBy": "net.transino.rce.app.biz.impl.DecisionEngineBizImpl",
"mobilePhone": "13213571926",
"createTime": "2018-03-30 15:49:01",
"durationSecond": 4.310,
"name": "常乐鑫",
"errorStack": ""
},
"isSuccess": true
}
最后是贴一下kettle转化配置文件k3.ktr内容:
<?xml version="1.0" encoding="UTF-8"?>
<transformation>
<info>
<name>k3</name>
<description />
<extended_description />
<trans_version />
<trans_type>Normal</trans_type>
<directory>/</directory>
<parameters>
</parameters>
<log>
<trans-log-table>
<connection />
<schema />
<table />
<size_limit_lines />
<interval />
<timeout_days />
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>TRANSNAME</id>
<enabled>Y</enabled>
<name>TRANSNAME</name>
</field>
<field>
<id>STATUS</id>
<enabled>Y</enabled>
<name>STATUS</name>
</field>
<field>
<id>LINES_READ</id>
<enabled>Y</enabled>
<name>LINES_READ</name>
<subject />
</field>
<field>
<id>LINES_WRITTEN</id>
<enabled>Y</enabled>
<name>LINES_WRITTEN</name>
<subject />
</field>
<field>
<id>LINES_UPDATED</id>
<enabled>Y</enabled>
<name>LINES_UPDATED</name>
<subject />
</field>
<field>
<id>LINES_INPUT</id>
<enabled>Y</enabled>
<name>LINES_INPUT</name>
<subject />
</field>
<field>
<id>LINES_OUTPUT</id>
<enabled>Y</enabled>
<name>LINES_OUTPUT</name>
<subject />
</field>
<field>
<id>LINES_REJECTED</id>
<enabled>Y</enabled>
<name>LINES_REJECTED</name>
<subject />
</field>
<field>
<id>ERRORS</id>
<enabled>Y</enabled>
<name>ERRORS</name>
</field>
<field>
<id>STARTDATE</id>
<enabled>Y</enabled>
<name>STARTDATE</name>
</field>
<field>
<id>ENDDATE</id>
<enabled>Y</enabled>
<name>ENDDATE</name>
</field>
<field>
<id>LOGDATE</id>
<enabled>Y</enabled>
<name>LOGDATE</name>
</field>
<field>
<id>DEPDATE</id>
<enabled>Y</enabled>
<name>DEPDATE</name>
</field>
<field>
<id>REPLAYDATE</id>
<enabled>Y</enabled>
<name>REPLAYDATE</name>
</field>
<field>
<id>LOG_FIELD</id>
<enabled>Y</enabled>
<name>LOG_FIELD</name>
</field>
<field>
<id>EXECUTING_SERVER</id>
<enabled>N</enabled>
<name>EXECUTING_SERVER</name>
</field>
<field>
<id>EXECUTING_USER</id>
<enabled>N</enabled>
<name>EXECUTING_USER</name>
</field>
<field>
<id>CLIENT</id>
<enabled>N</enabled>
<name>CLIENT</name>
</field>
</trans-log-table>
<perf-log-table>
<connection />
<schema />
<table />
<interval />
<timeout_days />
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>SEQ_NR</id>
<enabled>Y</enabled>
<name>SEQ_NR</name>
</field>
<field>
<id>LOGDATE</id>
<enabled>Y</enabled>
<name>LOGDATE</name>
</field>
<field>
<id>TRANSNAME</id>
<enabled>Y</enabled>
<name>TRANSNAME</name>
</field>
<field>
<id>STEPNAME</id>
<enabled>Y</enabled>
<name>STEPNAME</name>
</field>
<field>
<id>STEP_COPY</id>
<enabled>Y</enabled>
<name>STEP_COPY</name>
</field>
<field>
<id>LINES_READ</id>
<enabled>Y</enabled>
<name>LINES_READ</name>
</field>
<field>
<id>LINES_WRITTEN</id>
<enabled>Y</enabled>
<name>LINES_WRITTEN</name>
</field>
<field>
<id>LINES_UPDATED</id>
<enabled>Y</enabled>
<name>LINES_UPDATED</name>
</field>
<field>
<id>LINES_INPUT</id>
<enabled>Y</enabled>
<name>LINES_INPUT</name>
</field>
<field>
<id>LINES_OUTPUT</id>
<enabled>Y</enabled>
<name>LINES_OUTPUT</name>
</field>
<field>
<id>LINES_REJECTED</id>
<enabled>Y</enabled>
<name>LINES_REJECTED</name>
</field>
<field>
<id>ERRORS</id>
<enabled>Y</enabled>
<name>ERRORS</name>
</field>
<field>
<id>INPUT_BUFFER_ROWS</id>
<enabled>Y</enabled>
<name>INPUT_BUFFER_ROWS</name>
</field>
<field>
<id>OUTPUT_BUFFER_ROWS</id>
<enabled>Y</enabled>
<name>OUTPUT_BUFFER_ROWS</name>
</field>
</perf-log-table>
<channel-log-table>
<connection />
<schema />
<table />
<timeout_days />
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>LOG_DATE</id>
<enabled>Y</enabled>
<name>LOG_DATE</name>
</field>
<field>
<id>LOGGING_OBJECT_TYPE</id>
<enabled>Y</enabled>
<name>LOGGING_OBJECT_TYPE</name>
</field>
<field>
<id>OBJECT_NAME</id>
<enabled>Y</enabled>
<name>OBJECT_NAME</name>
</field>
<field>
<id>OBJECT_COPY</id>
<enabled>Y</enabled>
<name>OBJECT_COPY</name>
</field>
<field>
<id>REPOSITORY_DIRECTORY</id>
<enabled>Y</enabled>
<name>REPOSITORY_DIRECTORY</name>
</field>
<field>
<id>FILENAME</id>
<enabled>Y</enabled>
<name>FILENAME</name>
</field>
<field>
<id>OBJECT_ID</id>
<enabled>Y</enabled>
<name>OBJECT_ID</name>
</field>
<field>
<id>OBJECT_REVISION</id>
<enabled>Y</enabled>
<name>OBJECT_REVISION</name>
</field>
<field>
<id>PARENT_CHANNEL_ID</id>
<enabled>Y</enabled>
<name>PARENT_CHANNEL_ID</name>
</field>
<field>
<id>ROOT_CHANNEL_ID</id>
<enabled>Y</enabled>
<name>ROOT_CHANNEL_ID</name>
</field>
</channel-log-table>
<step-log-table>
<connection />
<schema />
<table />
<timeout_days />
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>LOG_DATE</id>
<enabled>Y</enabled>
<name>LOG_DATE</name>
</field>
<field>
<id>TRANSNAME</id>
<enabled>Y</enabled>
<name>TRANSNAME</name>
</field>
<field>
<id>STEPNAME</id>
<enabled>Y</enabled>
<name>STEPNAME</name>
</field>
<field>
<id>STEP_COPY</id>
<enabled>Y</enabled>
<name>STEP_COPY</name>
</field>
<field>
<id>LINES_READ</id>
<enabled>Y</enabled>
<name>LINES_READ</name>
</field>
<field>
<id>LINES_WRITTEN</id>
<enabled>Y</enabled>
<name>LINES_WRITTEN</name>
</field>
<field>
<id>LINES_UPDATED</id>
<enabled>Y</enabled>
<name>LINES_UPDATED</name>
</field>
<field>
<id>LINES_INPUT</id>
<enabled>Y</enabled>
<name>LINES_INPUT</name>
</field>
<field>
<id>LINES_OUTPUT</id>
<enabled>Y</enabled>
<name>LINES_OUTPUT</name>
</field>
<field>
<id>LINES_REJECTED</id>
<enabled>Y</enabled>
<name>LINES_REJECTED</name>
</field>
<field>
<id>ERRORS</id>
<enabled>Y</enabled>
<name>ERRORS</name>
</field>
<field>
<id>LOG_FIELD</id>
<enabled>N</enabled>
<name>LOG_FIELD</name>
</field>
</step-log-table>
<metrics-log-table>
<connection />
<schema />
<table />
<timeout_days />
<field>
<id>ID_BATCH</id>
<enabled>Y</enabled>
<name>ID_BATCH</name>
</field>
<field>
<id>CHANNEL_ID</id>
<enabled>Y</enabled>
<name>CHANNEL_ID</name>
</field>
<field>
<id>LOG_DATE</id>
<enabled>Y</enabled>
<name>LOG_DATE</name>
</field>
<field>
<id>METRICS_DATE</id>
<enabled>Y</enabled>
<name>METRICS_DATE</name>
</field>
<field>
<id>METRICS_CODE</id>
<enabled>Y</enabled>
<name>METRICS_CODE</name>
</field>
<field>
<id>METRICS_DESCRIPTION</id>
<enabled>Y</enabled>
<name>METRICS_DESCRIPTION</name>
</field>
<field>
<id>METRICS_SUBJECT</id>
<enabled>Y</enabled>
<name>METRICS_SUBJECT</name>
</field>
<field>
<id>METRICS_TYPE</id>
<enabled>Y</enabled>
<name>METRICS_TYPE</name>
</field>
<field>
<id>METRICS_VALUE</id>
<enabled>Y</enabled>
<name>METRICS_VALUE</name>
</field>
</metrics-log-table>
</log>
<maxdate>
<connection />
<table />
<field />
<offset>0.0</offset>
<maxdiff>0.0</maxdiff>
</maxdate>
<size_rowset>10000</size_rowset>
<sleep_time_empty>50</sleep_time_empty>
<sleep_time_full>50</sleep_time_full>
<unique_connections>N</unique_connections>
<feedback_shown>Y</feedback_shown>
<feedback_size>50000</feedback_size>
<using_thread_priorities>Y</using_thread_priorities>
<shared_objects_file />
<capture_step_performance>N</capture_step_performance>
<step_performance_capturing_delay>1000</step_performance_capturing_delay>
<step_performance_capturing_size_limit>100</step_performance_capturing_size_limit>
<dependencies>
</dependencies>
<partitionschemas>
</partitionschemas>
<slaveservers>
</slaveservers>
<clusterschemas>
</clusterschemas>
<created_user>-</created_user>
<created_date>2018/03/30 20:06:19.433</created_date>
<modified_user>-</modified_user>
<modified_date>2018/03/30 20:06:19.433</modified_date>
<key_for_session_key />
<is_key_private>N</is_key_private>
</info>
<notepads>
</notepads>
<order>
<hop>
<from>文件内容加载至内存</from>
<to>JSON Input</to>
<enabled>Y</enabled>
</hop>
<hop>
<from>JSON Input</from>
<to>文本文件输出</to>
<enabled>Y</enabled>
</hop>
</order>
<step>
<name>JSON Input</name>
<type>JsonInput</type>
<description />
<distribute>Y</distribute>
<custom_distribution />
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name />
</partitioning>
<include>N</include>
<include_field />
<rownum>N</rownum>
<addresultfile>N</addresultfile>
<readurl>N</readurl>
<removeSourceField>N</removeSourceField>
<IsIgnoreEmptyFile>N</IsIgnoreEmptyFile>
<doNotFailIfNoFile>Y</doNotFailIfNoFile>
<ignoreMissingPath>Y</ignoreMissingPath>
<rownum_field />
<file>
<name />
<filemask />
<exclude_filemask />
<file_required>N</file_required>
<include_subfolders>N</include_subfolders>
</file>
<fields>
<field>
<name>f2</name>
<path>$.responseData</path>
<type>String</type>
<format />
<currency />
<decimal />
<group />
<length>-1</length>
<precision>-1</precision>
<trim_type>none</trim_type>
<repeat>N</repeat>
</field>
<field>
<name>f3</name>
<path>$.responseData.rcAppId</path>
<type>String</type>
<format />
<currency />
<decimal />
<group />
<length>-1</length>
<precision>-1</precision>
<trim_type>none</trim_type>
<repeat>N</repeat>
</field>
<field>
<name>f4</name>
<path>$.responseData.备注</path>
<type>String</type>
<format />
<currency />
<decimal />
<group />
<length>-1</length>
<precision>-1</precision>
<trim_type>none</trim_type>
<repeat>N</repeat>
</field>
</fields>
<limit>0</limit>
<IsInFields>Y</IsInFields>
<IsAFile>N</IsAFile>
<valueField>f1</valueField>
<shortFileFieldName />
<pathFieldName />
<hiddenFieldName />
<lastModificationTimeFieldName />
<uriNameFieldName />
<rootUriNameFieldName />
<extensionFieldName />
<sizeFieldName />
<cluster_schema />
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>480</xloc>
<yloc>400</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>文件内容加载至内存</name>
<type>LoadFileInput</type>
<description />
<distribute>Y</distribute>
<custom_distribution />
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name />
</partitioning>
<include>N</include>
<include_field />
<rownum>N</rownum>
<addresultfile>Y</addresultfile>
<IsIgnoreEmptyFile>N</IsIgnoreEmptyFile>
<IsIgnoreMissingPath>N</IsIgnoreMissingPath>
<rownum_field />
<encoding>UTF-8</encoding>
<file>
<name>D:\223.json</name>
<filemask />
<exclude_filemask />
<file_required>否</file_required>
<include_subfolders>N</include_subfolders>
</file>
<fields>
<field>
<name>f1</name>
<element_type>content</element_type>
<type>None</type>
<format />
<currency />
<decimal />
<group />
<length>-1</length>
<precision>-1</precision>
<trim_type>none</trim_type>
<repeat>N</repeat>
</field>
</fields>
<limit>0</limit>
<IsInFields>N</IsInFields>
<DynamicFilenameField />
<shortFileFieldName />
<pathFieldName />
<hiddenFieldName />
<lastModificationTimeFieldName />
<uriNameFieldName />
<rootUriNameFieldName />
<extensionFieldName />
<cluster_schema />
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>192</xloc>
<yloc>432</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>文本文件输出</name>
<type>TextFileOutput</type>
<description />
<distribute>Y</distribute>
<custom_distribution />
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name />
</partitioning>
<separator>,</separator>
<enclosure>"</enclosure>
<enclosure_forced>N</enclosure_forced>
<enclosure_fix_disabled>N</enclosure_fix_disabled>
<header>Y</header>
<footer>N</footer>
<format>DOS</format>
<compression>None</compression>
<encoding />
<endedLine />
<fileNameInField>N</fileNameInField>
<fileNameField />
<create_parent_folder>Y</create_parent_folder>
<file>
<name>D:\file2</name>
<is_command>N</is_command>
<servlet_output>N</servlet_output>
<do_not_open_new_file_init>N</do_not_open_new_file_init>
<extention>csv</extention>
<append>N</append>
<split>N</split>
<haspartno>N</haspartno>
<add_date>N</add_date>
<add_time>N</add_time>
<SpecifyFormat>N</SpecifyFormat>
<date_time_format />
<add_to_result_filenames>Y</add_to_result_filenames>
<pad>N</pad>
<fast_dump>N</fast_dump>
<splitevery>0</splitevery>
</file>
<fields>
<field>
<name>f2</name>
<type>String</type>
<format />
<currency />
<decimal />
<group />
<nullif />
<trim_type>none</trim_type>
<length>-1</length>
<precision>-1</precision>
</field>
<field>
<name>f3</name>
<type>String</type>
<format />
<currency />
<decimal />
<group />
<nullif />
<trim_type>none</trim_type>
<length>-1</length>
<precision>-1</precision>
</field>
<field>
<name>f4</name>
<type>String</type>
<format />
<currency />
<decimal />
<group />
<nullif />
<trim_type>none</trim_type>
<length>-1</length>
<precision>-1</precision>
</field>
</fields>
<cluster_schema />
<remotesteps>
<input>
</input>
<output>
</output>
</remotesteps>
<GUI>
<xloc>704</xloc>
<yloc>432</yloc>
<draw>Y</draw>
</GUI>
</step>
<step_error_handling>
</step_error_handling>
<slave-step-copy-partition-distribution>
</slave-step-copy-partition-distribution>
<slave_transformation>N</slave_transformation>
</transformation>
===================================
JSONPath语法
返回数组的最后两个值
List<String> lastTwoName = context.read("$.result.records[-2:].name");