Эх сурвалжийг харах

修改token请求方法,解决数据中台访问报错问题

Lin Qilong 3 өдөр өмнө
parent
commit
ce8c374aa3

+ 36 - 2
pom.xml

@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.example</groupId>
     <artifactId>sh-model-gateway</artifactId>
-    <packaging>war</packaging>
+    <packaging>jar</packaging>
     <version>1.0-SNAPSHOT</version>
     <name>sh-model-gateway</name>
 
@@ -151,8 +151,42 @@
             <artifactId>okhttp</artifactId>
         </dependency>
 
+        <!-- xml解析工具类 -->
+        <dependency>
+            <groupId>org.dom4j</groupId>
+            <artifactId>dom4j</artifactId>
+            <version>2.1.4</version>
+        </dependency>
+
     </dependencies>
+
     <build>
-        <finalName>sh-model-gateway</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.5.15</version>
+                <configuration>
+                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>3.1.0</version>
+                <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                    <warName>${project.artifactId}</warName>
+                </configuration>
+            </plugin>
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
     </build>
 </project>

+ 142 - 0
src/main/java/cn/com/goldenwater/core/api/BizDataApiRequest.java

@@ -0,0 +1,142 @@
+package cn.com.goldenwater.core.api;
+
+import cn.com.goldenwater.core.domain.BizDataApi;
+import cn.com.goldenwater.core.domain.BizDataApiParam;
+import cn.com.goldenwater.utils.HttpRequestUtil;
+import cn.com.goldenwater.utils.JsonUtils;
+import cn.com.goldenwater.utils.StringUtils;
+import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.fastjson2.JSONPath;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.util.*;
+
+@Slf4j
+public class BizDataApiRequest {
+
+    public static Object requestByQueryOptions(String queryOptions) throws IOException {
+        return requestByQueryOptions(queryOptions, null);
+    }
+
+    public static Object requestByQueryOptions(String queryOptions, Map<String, String> updateParams) throws IOException {
+        BizDataApi apiConfigObj = JsonUtils.jsonToPojo(queryOptions, BizDataApi.class);
+        // 解析参数格式
+        Map<String, Object> params = parseKeyValueList(apiConfigObj.getParams());
+        if (updateParams != null) {
+            for (String key : params.keySet()) {
+                if (updateParams.containsKey(key)) {
+                    params.put(key, updateParams.get(key));
+                }
+            }
+        }
+        Map<String, Object> cookies = parseKeyValueList(apiConfigObj.getCookies());
+        Map<String, Object> headers = parseKeyValueList(apiConfigObj.getHeaders());
+        Map<String, String> headerMap = new HashMap<>();
+        for (String key : headers.keySet()) {
+            headerMap.put(key, String.valueOf(headers.get(key)));
+        }
+        String body = parseBody(apiConfigObj.getBody(), updateParams);
+        String responseResolution = apiConfigObj.getResponseResolution();
+
+        String responseString = HttpRequestUtil.getDataByRequest(
+                apiConfigObj.getUrl(),
+                apiConfigObj.getMethod(),
+                headerMap,
+                body
+        );
+
+//        String responseString = OkHttpUtils.executeRequest(
+//                apiConfigObj.getUrl(),
+//                apiConfigObj.getMethod(),
+//                params,
+//                body,
+//                cookies,
+//                headers
+//        );
+
+        if (StringUtils.isNotBlank(responseString)) {
+            Object result = null;
+            if (responseString.startsWith("[")) {
+                List<JSONObject> responseObj = JsonUtils.jsonToList(responseString, JSONObject.class);
+                result = responseObj;
+                if (StringUtils.isNotBlank(responseResolution)) {
+                    result = JSONPath.eval(responseObj, responseResolution);
+                }
+            } else {
+                JSONObject responseObj = JsonUtils.jsonToPojo(responseString, JSONObject.class);
+                result = responseObj;
+                if (StringUtils.isNotBlank(responseResolution)) {
+                    result = JSONPath.eval(responseObj, responseResolution);
+                }
+            }
+            return result;
+        }
+
+        log.warn("返回数据异常:{}", responseString);
+        return responseString;
+    }
+
+    /**
+     * 将键值对数组解析为Map
+     */
+    private static Map<String, Object> parseKeyValueList(List<BizDataApiParam> keyValueList) {
+        Map<String, Object> resultMap = new HashMap<>();
+        if (keyValueList == null) {
+            return resultMap;
+        }
+
+        for (BizDataApiParam item : keyValueList) {
+            String key = item.getKey();
+            Object value = item.getValue();
+            String type = item.getType();
+
+            // 根据类型处理值
+            if ("array".equals(type) && value instanceof List) {
+                resultMap.put(key, Collections.singletonList(value));
+            } else {
+                resultMap.put(key, value);
+            }
+        }
+        return resultMap;
+    }
+
+    /**
+     * 解析body字段
+     */
+    private static String parseBody(List<BizDataApiParam> bodyArray, Map<String, String> updateParams) {
+        if (bodyArray == null) {
+            return null;
+        }
+
+        JSONObject bodyObj = new JSONObject();
+        bodyArray.forEach(item -> {
+            String key = item.getKey();
+            Object value = item.getValue();
+            String type = item.getType();
+
+            // 根据类型处理值
+            if ("array".equals(type) && value instanceof List) {
+                bodyObj.put(key, value);
+            } else {
+                bodyObj.put(key, value);
+            }
+        });
+
+        if (updateParams != null) {
+            for (String key : bodyObj.keySet()) {
+                if (updateParams.containsKey(key)) {
+                    bodyObj.put(key, updateParams.get(key));
+                }
+            }
+        }
+
+        return bodyObj.toJSONString();
+    }
+
+    public static List<BizDataApiParam> getColumns(String queryOptions) {
+        BizDataApi apiConfigObj = JsonUtils.jsonToPojo(queryOptions, BizDataApi.class);
+        return Optional.ofNullable(apiConfigObj).map(BizDataApi::getResponse).orElse(null);
+    }
+
+}

+ 28 - 0
src/main/java/cn/com/goldenwater/core/domain/BizDataApi.java

@@ -0,0 +1,28 @@
+package cn.com.goldenwater.core.domain;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+import java.util.List;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@Data
+public class BizDataApi {
+
+    private String url;
+
+    private String method;
+
+    private List<BizDataApiParam> params;
+
+    private List<BizDataApiParam> body;
+
+    private List<BizDataApiParam> cookies;
+
+    private List<BizDataApiParam> headers;
+
+    private String responseResolution;
+
+    private List<BizDataApiParam> response;
+
+}

+ 27 - 0
src/main/java/cn/com/goldenwater/core/domain/BizDataApiParam.java

@@ -0,0 +1,27 @@
+package cn.com.goldenwater.core.domain;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@Data
+public class BizDataApiParam {
+
+    private String id;
+    private String key;
+    private Object value;
+    private String title;
+    private String type;
+
+    public BizDataApiParam(String key, Object value, String type) {
+        this.key = key;
+        this.value = value;
+        this.type = type;
+    }
+
+    public BizDataApiParam(String key, Object value) {
+        this.key = key;
+        this.value = value;
+    }
+
+}

+ 49 - 0
src/main/java/cn/com/goldenwater/enums/DataType.java

@@ -0,0 +1,49 @@
+package cn.com.goldenwater.enums;
+
+import cn.com.goldenwater.utils.JsonUtils;
+import cn.com.goldenwater.utils.StringDataTypeUtils;
+import cn.com.goldenwater.utils.Xml2JsonUtils;
+import com.alibaba.fastjson2.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author LinQiLong
+ * @date 2023/4/26 10:38
+ */
+@Slf4j
+public enum DataType {
+    /**
+     * json 格式
+     */
+    JSON {
+        @Override
+        public JSONObject toJSONObject(String dataStr) {
+            return JsonUtils.jsonToPojo(dataStr, JSONObject.class);
+        }
+    },
+    XML {
+        @Override
+        public JSONObject toJSONObject(String dataStr) {
+            JSONObject resObj = Xml2JsonUtils.xml2Json(dataStr);
+            // 2. 查询指定数据
+            return resObj;
+        }
+    },
+    STRING, NUMBER;
+
+    public static JSONObject getDataByJSON(String dataStr) {
+        // 判断类型
+        String type = StringDataTypeUtils.getType(dataStr);
+        log.info(">> 请求数据返回格式:{}", type);
+        DataType dataType = DataType.valueOf(type);
+        // 转换成 JSONObject
+        return dataType.toJSONObject(dataStr);
+    }
+
+    public JSONObject toJSONObject(String dataStr) {
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("data", dataStr);
+        return jsonObject;
+    }
+
+}

+ 7 - 30
src/main/java/cn/com/goldenwater/filter/ThirdPartyAuthFilter.java

@@ -1,13 +1,10 @@
 package cn.com.goldenwater.filter;
 
+import cn.com.goldenwater.core.api.BizDataApiRequest;
 import cn.com.goldenwater.core.redis.RedisCache;
 import cn.com.goldenwater.domain.GatewayRoutes;
 import cn.com.goldenwater.service.GatewayRoutesService;
-import cn.com.goldenwater.utils.JsonUtils;
-import cn.com.goldenwater.utils.OkHttpUtils;
 import cn.com.goldenwater.utils.StringUtils;
-import com.alibaba.fastjson2.JSONObject;
-import com.alibaba.fastjson2.JSONPath;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
 import org.springframework.cloud.gateway.filter.GlobalFilter;
@@ -18,8 +15,8 @@ import org.springframework.web.server.ServerWebExchange;
 import org.springframework.web.util.UriComponentsBuilder;
 import reactor.core.publisher.Mono;
 
+import java.io.IOException;
 import java.net.URI;
-import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 @Component
@@ -47,7 +44,11 @@ public class ThirdPartyAuthFilter implements GlobalFilter, Ordered {
             String thirdPartyAuthToken = redisCache.getCacheObject(key);
 
             if (StringUtils.isBlank(thirdPartyAuthToken)) {
-                thirdPartyAuthToken = requestByQueryOptions(gatewayRoutes.getAuthQueryOptions());
+                try {
+                    thirdPartyAuthToken = (String) BizDataApiRequest.requestByQueryOptions(gatewayRoutes.getAuthQueryOptions());
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
                 redisCache.setCacheObject(key, thirdPartyAuthToken, Integer.parseInt(gatewayRoutes.getAuthExpirationTime()), TimeUnit.MINUTES);
             }
 
@@ -72,30 +73,6 @@ public class ThirdPartyAuthFilter implements GlobalFilter, Ordered {
         return chain.filter(exchange);
     }
 
-    private String requestByQueryOptions(String queryOptions) {
-        JSONObject apiConfigObj = JsonUtils.jsonToPojo(queryOptions, JSONObject.class);
-        Map<String, Object> params = apiConfigObj.getJSONObject("params");
-        Map<String, Object> cookies = apiConfigObj.getJSONObject("cookies");
-        Map<String, Object> headers = apiConfigObj.getJSONObject("headers");
-        String responseResolution = apiConfigObj.getString("responseResolution");
-
-        String responseString = OkHttpUtils.executeRequest(
-                apiConfigObj.getString("url"),
-                apiConfigObj.getString("method"),
-                params,
-                apiConfigObj.getString("body"),
-                cookies,
-                headers
-        );
-
-        JSONObject responseObj = JsonUtils.jsonToPojo(responseString, JSONObject.class);
-        String result = responseString;
-        if (StringUtils.isNotBlank(responseResolution)) {
-            result = String.valueOf(JSONPath.eval(responseObj, responseResolution));
-        }
-        return result;
-    }
-
     @Override
     public int getOrder() {
         return -70;

+ 141 - 0
src/main/java/cn/com/goldenwater/utils/HttpRequestUtil.java

@@ -0,0 +1,141 @@
+package cn.com.goldenwater.utils;
+
+import cn.com.goldenwater.enums.DataType;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * @description: http请求--该工具类只适用于报表设计-rest接口数据源
+ * @date: 2021/5/17 21:31
+ * 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
+ */
+public class HttpRequestUtil {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(HttpRequestUtil.class);
+
+    /**
+     * 发送请求查询数据
+     *
+     * @param requestUrl    请求路径
+     * @param requestMethod 请求方式
+     * @param requestBody   请求体
+     * @param requestHeader 请求头
+     * @return 响应结果
+     * @throws IOException 异常
+     */
+    public static String getDataByRequest(String requestUrl, String requestMethod, Map<String, String> requestHeader, String requestBody) throws IOException {
+        LOGGER.info(">> 访问接口:\n请求地址:{}\n请求方式:{}\n请求头:{}\n请求参数:{}", requestUrl, requestMethod, requestHeader != null ? JSON.toJSON(requestHeader) : "", requestBody);
+        String result;
+        BufferedReader in = null;
+        DataOutputStream out = null;
+        if ("GET".equalsIgnoreCase(requestMethod) && !StringUtils.isEmpty(requestBody)) {
+            Map<String, Object> bodyMap = JsonUtils.jsonToPojo(requestBody, Map.class);
+            StringBuilder urlSb = new StringBuilder(requestUrl).append("?");
+            for (String key : bodyMap.keySet()) {
+                urlSb.append(key).append("=").append(bodyMap.get(key)).append("&");
+            }
+            urlSb.deleteCharAt(urlSb.length() - 1);
+            requestUrl = urlSb.toString().replaceAll(" ", "%20");
+        }
+        HttpURLConnection conn = getHttpConnection(requestUrl, requestMethod);
+        try {
+            if (!"GET".equalsIgnoreCase(requestMethod) && !StringUtils.isEmpty(requestBody)) {
+                conn.setDoInput(true);
+                conn.setDoOutput(true);
+                if (requestHeader != null && !requestHeader.isEmpty()) {
+                    requestHeader.forEach(conn::setRequestProperty);
+                }
+                out = new DataOutputStream(conn.getOutputStream());
+                out.writeBytes(requestBody);
+            }
+            conn.connect();
+            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+            StringBuilder sb = new StringBuilder();
+            String temp;
+            while ((temp = in.readLine()) != null) {
+                sb.append(temp).append(" ");
+            }
+            result = sb.toString();
+            LOGGER.info(">> 访问结果:{}", result);
+            return result;
+        } catch (IOException ex) {
+            LOGGER.error(">> 访问接口失败:{}", ex.getMessage(), ex);
+        } finally {
+            if (in != null) {
+                in.close();
+            }
+            if (out != null) {
+                out.flush();
+                out.close();
+            }
+        }
+        return null;
+    }
+
+    public static JSONObject getRequest(String requestUrl) {
+        return getRequest(requestUrl, null);
+    }
+
+    public static JSONObject getRequest(String requestUrl, Map<String, Object> requestBody) {
+        return getJSONObjectByRequest(requestUrl, "GET", null, requestBody != null ? JsonUtils.objectToJson(requestBody) : null);
+    }
+
+    public static JSONObject getRequest(String requestUrl, Map<String, String> requestHeader, Map<String, Object> requestBody) {
+        return getJSONObjectByRequest(requestUrl, "GET", requestHeader, requestBody != null ? JsonUtils.objectToJson(requestBody) : null);
+    }
+
+    public static JSONObject postRequest(String requestUrl, Map<String, Object> requestBody) {
+        Map<String, String> requestHeader = new HashMap<>(1);
+        requestHeader.put("Content-Type", "application/json");
+        return getJSONObjectByRequest(requestUrl, "POST", requestHeader, requestBody != null ? JsonUtils.objectToJson(requestBody) : null);
+    }
+
+    public static JSONObject getJSONObjectByRequest(String requestUrl, String requestMethod, Map<String, String> requestHeader, String requestBody) {
+        try {
+            // 请求服务
+            String resStr = HttpRequestUtil.getDataByRequest(requestUrl, requestMethod, requestHeader, requestBody);
+            // 返回结果转换格式
+            return Optional.ofNullable(resStr).map(DataType::getDataByJSON).orElse(null);
+        } catch (IOException ignored) {
+        }
+        return null;
+    }
+
+    /**
+     * 查询HTTP请求连接
+     *
+     * @param requestUrl    请求路径
+     * @param requestMethod 请求方式
+     * @return 返回请求连接
+     */
+    private static HttpURLConnection getHttpConnection(String requestUrl, String requestMethod) {
+        HttpURLConnection conn;
+        try {
+            URL uri = new URL(requestUrl);
+            conn = (HttpURLConnection) uri.openConnection();
+            // requestMethod: POST, PUT, DELETE, GET
+            conn.setRequestMethod(requestMethod);
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            conn.setConnectTimeout(120000); //60 secs
+            conn.setReadTimeout(120000); //60 secs
+            conn.setRequestProperty("Accept-Charset", "UTF-8");
+            conn.setRequestProperty("contentType", "UTF-8");
+        } catch (Exception ex) {
+            throw new RuntimeException("connection failed.");
+        }
+        return conn;
+    }
+}

+ 99 - 0
src/main/java/cn/com/goldenwater/utils/StringDataTypeUtils.java

@@ -0,0 +1,99 @@
+package cn.com.goldenwater.utils;
+
+import com.alibaba.fastjson2.JSON;
+import org.xml.sax.InputSource;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.StringReader;
+
+/**
+ * @author LinQiLong
+ * @date 2023/4/26 10:19
+ */
+public class StringDataTypeUtils {
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) {
+        String str1 = "45";
+        String str2 = "wangningwei";
+        String str3 = "{cd:\"wangningwei\"}";
+        String str4 = "<av>fvbfdyr</av>";
+        System.out.println("string1::" + getType(str1));
+        System.out.println("string2::" + getType(str2));
+        System.out.println("string3::" + getType(str3));
+        System.out.println("string4::" + getType(str4));
+    }
+
+    public static String getType(String string) {
+        if (isNumber(string)) {
+            return "NUMBER";
+        } else if (isJson(string)) {
+            return "JSON";
+        } else if (isXML(string)) {
+            return "XML";
+        } else {
+            return "STRING";
+        }
+    }
+
+    /**
+     * 判断字符串是否是数字
+     */
+    public static boolean isNumber(String value) {
+        return isInteger(value) || isDouble(value);
+    }
+
+    /**
+     * 判断字符串是否是整数
+     */
+    public static boolean isInteger(String value) {
+        try {
+            Integer.parseInt(value);
+            return true;
+        } catch (NumberFormatException e) {
+            return false;
+        }
+    }
+
+    /**
+     * 判断字符串是否是浮点数
+     */
+    public static boolean isDouble(String value) {
+        try {
+            Double.parseDouble(value);
+            return value.contains(".");
+        } catch (NumberFormatException e) {
+            return false;
+        }
+    }
+
+    /**
+     * 判断是否是json结构
+     */
+    public static boolean isJson(String value) {
+        try {
+            JSON.parse(value);
+        } catch (Throwable e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 判断是否是xml结构
+     */
+    public static boolean isXML(String value) {
+        try {
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder builder = factory.newDocumentBuilder();
+            InputSource is = new InputSource(new StringReader(value));
+            builder.parse(is);
+        } catch (Exception e) {
+            return false;
+        }
+        return true;
+    }
+}

+ 99 - 0
src/main/java/cn/com/goldenwater/utils/Xml2JsonUtils.java

@@ -0,0 +1,99 @@
+package cn.com.goldenwater.utils;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.dom4j.*;
+
+import java.util.List;
+
+/**
+ * * @ClassName XmlToJsonUtil
+ * * @Author gxy
+ * * @Desc xml转json
+ *
+ * @author LinQiLong
+ * @date 2023/3/27 17:36
+ */
+@Slf4j
+public class Xml2JsonUtils {
+
+    /**
+     * xml转json
+     *
+     * @param xmlStr
+     * @return
+     * @throws DocumentException
+     */
+    public static JSONObject xml2Json(String xmlStr) {
+        try {
+            Document doc = DocumentHelper.parseText(xmlStr);
+            return dom4j2Json(doc.getRootElement());
+        } catch (DocumentException e) {
+            log.error(e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /**
+     * xml转json
+     *
+     * @param element
+     */
+    private static JSONObject dom4j2Json(Element element) {
+        JSONObject json = new JSONObject();
+        // 如果是属性
+        for (Object o : element.attributes()) {
+            Attribute attr = (Attribute) o;
+            if (StringUtils.isNotBlank(attr.getValue())) {
+                json.put("@" + attr.getName(), attr.getValue());
+            }
+        }
+        List<Element> chdEl = element.elements();
+        if (chdEl.isEmpty() && StringUtils.isNotBlank(element.getText())) {
+            // 如果没有子元素,只有一个值
+            json.put(element.getName(), element.getText());
+        }
+        for (Element e : chdEl) {
+            // 有子元素
+            if (!e.elements().isEmpty()) {
+                // 子元素也有子元素
+                JSONObject chdjson = dom4j2Json(e);
+                Object o = json.get(e.getName());
+                if (o != null) {
+                    JSONArray jsona = null;
+                    if (o instanceof JSONObject) {
+                        // 如果此元素已存在,则转为jsonArray
+                        JSONObject jsono = (JSONObject) o;
+                        json.remove(e.getName());
+                        jsona = new JSONArray();
+                        jsona.add(jsono);
+                        jsona.add(chdjson);
+                    }
+                    if (o instanceof JSONArray) {
+                        jsona = (JSONArray) o;
+                        jsona.add(chdjson);
+                    }
+                    json.put(e.getName(), jsona);
+                } else {
+                    if (!chdjson.isEmpty()) {
+                        json.put(e.getName(), chdjson);
+                    }
+                }
+            } else {
+                // 子元素没有子元素
+                for (Object o : element.attributes()) {
+                    Attribute attr = (Attribute) o;
+                    if (StringUtils.isNotBlank(attr.getValue())) {
+                        json.put("@" + attr.getName(), attr.getValue());
+                    }
+                }
+                if (!e.getText().isEmpty()) {
+                    json.put(e.getName(), e.getText());
+                }
+            }
+        }
+        return json;
+    }
+}