将 XML 转换为 JSON 和 Vice Versa,以及如何在发出 XML 请求时识别 REST 端点?

Posted

技术标签:

【中文标题】将 XML 转换为 JSON 和 Vice Versa,以及如何在发出 XML 请求时识别 REST 端点?【英文标题】:Convert XML to JSON and Vice Versa and also how to identify REST endpoint while making XML Request? 【发布时间】:2020-04-13 04:49:44 【问题描述】:

在发布这个问题之前我做了很多研究,但是我没有得到适当的指导。 我的公司已通过Proxy/Gateway 将 REST 端点暴露给外部世界。大约 1000 名客户注册了代理/网关并向基于 SOAP 的系统发出 XML 请求(部署在 WebSphere App Server (WAS) V7.5 上)。现在,我们开发了只支持 JSON 的新系统,并希望指向部署在 PCF (Pivotal Cloud Foundry) 上的新开发系统。

这里我们不想让消费者做任何改变。

现在,我们正在尝试开发Adapter (Spring Boot Project),它将 XML 请求转换为 JSON 向新系统发出请求并以 JSON 格式获得响应,Adapter (Spring Boot Project) 再次将 JSON 转换为 XML。 在这里,JSON 响应和 XML 响应有时可能会有所不同。

现在,我真的无法决定调用哪个端点

String xml_data = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:urn=\"urn:ahc.com:dms:wsdls:organization\">\n" + 
        "   <soapenv:Header/>\n" + 
        "   <soapenv:Body>\n" + 
        "      <urn:getRoles>\n" + 
        "         <getRolesRequest>\n" + 
        "            <Type>ABC</Type>\n" + 
        "         </getRolesRequest>\n" + 
        "      </urn:getRoles>\n" + 
        "   </soapenv:Body>\n" + 
        "</soapenv:Envelope>";
JSONObject obj = XML.toJSONObject(xml_data);
System.out.println(obj);

它给了我以下响应。

"soapenv:Envelope":"soapenv:Body":"urn:getRoles":"getRolesRequest":"Type":"AYU","xmlns:soapenv":"http://schemas.xmlsoap.org/soap/envelope/","xmlns:urn":"urn:ahc.com:dms:wsdls:organization","soapenv:Header":""

有什么指导吗?

注意:我想从 JSON 对象中删除 &lt;soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\。此外,在将 JSON 转换为 XML 时,我想添加 &lt;soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\

【问题讨论】:

对不起,您在说什么endpoint?您不确定要使用 JSON 调用哪个 API 端点? 我假设你的代码在 REST 项目之外,你应该有 SOAP to REST 映射来帮助你找到 URL。一种解决方法是配置Gateway 以提供REST URL 作为header 我不确定Gateway 使用的是什么。许多网关为添加的每个端点提供配置。当在 URL 上发出请求时,我们可以要求它添加自定义标头,当它添加 REST url 作为标头时,您可以阅读它并进一步使用该路由您的呼叫。如果您的网关是另一个自定义编写的应用程序,我认为应该对其进行修改以支持此功能。 如果您的网关不支持它,另一种方法是配置您的adapter 应用程序以包含这些映射。配置您的环境以在初始应用程序加载时加载映射并使用它们来识别 REST 端点。 让我们continue this discussion in chat。 【参考方案1】:

如果您的网关支持为每个端点传递自定义标头,那将是执行此操作的理想方式。在这种情况下,它将在请求标头中发送 REST 端点,您可以使用它来转发呼叫。

如果网关不支持此类功能,您可以尝试修改您的Adapter 代码。

如果你想配置你的适配器来保存端点映射,你可以使用@ConfigurationProperties配置它

EndpointRegistry

import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

@EnableConfigurationProperties
@ConfigurationProperties(prefix = "endpoint")
@Component
public class EndpointRegistry 

    // top key - endpoint
    // one key - soapUrl
    // another key - restUrl
    private Map<String, Map<String, String>> api;

    public Map<String, Map<String, String>> getApi() 
        return api;
    

    public void setApi(Map<String, Map<String, String>> api) 
        this.api = api;
    

这将匹配您的application.properties 文件中提到的键模式,如下所示

endpoint.api.endpoint1.soapUrl=<soap-url>
endpoint.api.endpoint1.restUrl=<rest-url>

endpoint.api.endpoint2.soapUrl=<soap-url>
endpoint.api.endpoint2.restUrl=<rest-url>

现在,endpoint name 应该是唯一的。您可以决定密钥结构。这只是一个例子。

这是一个用于验证值的测试控制器:

import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/endpoints")
public class EndpointController 

    @Autowired
    EndpointRegistry registry;

    @GetMapping
    public Map<String, String> getRestUrl(String endpoint) 
        return registry.getApi().get(endpoint);
    

拨打GEThttp://localhost:8080/endpoints?endpoint=endpoint1

你应该得到


   "soapUrl":"<soap-url>",
   "restUrl":"<rest-url>"

这样,您就可以使用您的EndpointRegistry 获取所需的网址并拨打电话。

您可以使用 Spring 配置服务器为每个环境更新您的 application.properties。在这里查看:https://cloud.spring.io/spring-cloud-config/multi/multi__spring_cloud_config_server.html

同时,您可以配置 CI 管道以预先为每个环境添加这些属性。

【讨论】:

【参考方案2】:

您可以使用underscore-java 库。它具有读取 xml 和生成 json 的静态方法。

    String xmlData = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\""
    + " xmlns:urn=\"urn:ahc.com:dms:wsdls:organization\">\n"
    + "   <soapenv:Header/>\n"
    + "   <soapenv:Body>\n"
    + "      <urn:getRoles>\n"
    + "         <getRolesRequest>\n"
    + "            <Type>ABC</Type>\n"
    + "         </getRolesRequest>\n"
    + "      </urn:getRoles>\n"
    + "   </soapenv:Body>\n"
    + "</soapenv:Envelope>";
    Map<String, Object> jsonData = U.<Map<String, Object>>get(
        U.<Map<String, Object>>fromXmlWithoutNamespaces(xmlData), "Envelope.Body.getRoles");
    System.out.println(U.toJson(jsonData));

输出:


  "getRolesRequest": 
    "Type": "ABC"
  

【讨论】:

以上是关于将 XML 转换为 JSON 和 Vice Versa,以及如何在发出 XML 请求时识别 REST 端点?的主要内容,如果未能解决你的问题,请参考以下文章

需要基于 xml-mapping 将 POJO 转换为 XML 和 JSON 的工具

使用 Gson 将 XML 文件转换为 Json

JSON对象与XML相互转换工具类

将 Json 转换为 XML - 带有数组值的 Json

将 Json 转换为 Xml 的最简单方法

将 JSON 数组转换为 XML