简体   繁体   English

WSO2 ESB无法将完整的JSON数据转换为XML

[英]WSO2 ESB Unable to convert complete JSON data to XML

I am constructing a POC. 我正在建造一个POC。 And I created a pass through proxy service for Google Plus. 我为Google Plus创建了传递代理服务。 Without using any proxy service I get this is my output : 没有使用任何代理服务我得到这是我的输出:

 {
   "kind":"plus#person",
   "etag":"\"ExituU7aUpmkkfyD52VulzptThw/4J1clegrhxYC2fsJOu2XWCs1Ewg\"",
   "id":"117488614303967062311",
   "displayName":"Abhi NeoN",
   "name":{
      "familyName":"NeoN",
      "givenName":"Abhi"
   },
   "tagline":"hey guys ! ssup!! check out ma recnt videos... uploaded",
   "gender":"male",
   "aboutMe":"\u003cb\u003ehie, abhishek - ma full name \u003c/b\u003e\u003cdiv\u003e\u003cb\u003em a DANCER ,\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003ei luv ma dancing .\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003ei care ma dancing ,\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003ei jus hv a gr8 thng in me dats ma dancing.\u003c/b\u003e\u003c/div\u003e",
   "relationshipStatus":"single",
   "url":"https://plus.google.com/117488614303967062311",
   "image":{
      "url":"https://lh6.googleusercontent.com/-tF-ip0tUxD4/AAAAAAAAAAI/AAAAAAAAAAA/WKI3USUh_DA/photo.jpg?sz=50"
   },
   "urls":[
      {
         "value":"https://plus.google.com/117488614303967062311",
         "type":"profile"
      },
      {
         "value":"https://www.googleapis.com/plus/v1/people/117488614303967062311",
         "type":"json"
      }
   ],
   "organizations":[
      {
         "name":"our lady of nazareth high school",
         "title":"science",
         "type":"school"
      },
      {
         "name":"",
         "title":"BLUEBYTES",
         "type":"work"
      }
   ]
}

But when I try to do the same using a simple pass through service I get only : 但是当我尝试使用简单的传递服务来做同样的事情时,我只得到:

{
   "kind":"plus#person"
}

I read on the wso2esb site that they had a bug and the explanation given to resolve the bug was that json data received was not in the proper format. 我在wso2esb网站上看到他们有一个错误,解决这个错误的解释是收到的json数据格式不正确。 But now how do I resolve the problem. 但现在我该如何解决这个问题。 I mean is their any way I can manipulate the json data before the esb converts it into json data. 我的意思是他们可以在esb将其转换为json数据之前操纵json数据。

We have solved this issue in the latest release of ESB (version 4.5.0). 我们已在最新版本的ESB(版本4.5.0)中解决了此问题。 By default it comes with JSONMessageFormatter/JSONBuilder that can handle JSON payloads with multiple keys. 默认情况下,它附带了JSONMessageFormatter / JSONBuilder,它可以处理具有多个密钥的JSON有效负载。

We also came up with another solution for handling message flows that involve different types of JSON <--> XML (or JSON <--> JSON) conversions. 我们还提出了另一种处理消息流的解决方案,它涉及不同类型的JSON < - > XML(或JSON < - > JSON)转换。 JSONStreamBuilder and JSONStreamFormatter can be used to implement such scenarios with the 'script' mediator. JSONStreamBuilderJSONStreamFormatter可用于使用'script'介体实现此类场景。 Have a look at sample #441 in ESB 4.5.0. 看看ESB 4.5.0中的示例#441。

To run sample #441; 运行样本#441;

  • Add JSONStreamBuilder and JSONStreamFormatter as the builder and formatter for JSON in repository/conf/axis2/axis2.xml file 在repository / conf / axis2 / axis2.xml文件中添加JSONStreamBuilderJSONStreamFormatter作为JSON的构建器和格式化程序
  • Deploy SimpleStockQuoteService 部署SimpleStockQuoteService
  • Start the sample axis2server 启动示例axis2server
  • Run the JSON client with ' ant newjsonclient ' 使用' ant newjsonclient '运行JSON客户端

This is one of the limitations of the current axis2 JSON builder/formatter. 这是当前axis2 JSON构建器/格式化程序的限制之一。 We are currently working on a new builder/formatter pair for JSON that does not convert JSON <-> XML. 我们目前正在为JSON开发一个新的构建器/格式化程序对,它不转换JSON < - > XML。 Instead it(builder) stores the JSON message as a stream and the script mediator can be used to build a JSON object out of that stream. 相反,它(构建器)将JSON消息存储为流,并且脚本介体可用于从该流构建JSON对象。 For example, if we send {"a" : "x", "b" : "y"} as the request, within the ESB, we can manipulate this request as a JSON object with javascript. 例如,如果我们在ESB中发送{“a”:“x”,“b”:“y”}作为请求,我们可以使用javascript将此请求作为JSON对象进行操作。

var a = mc.getJSON().a.toString();
var b = mc.getJSON().b.toString();
mc.setPayloadXML(
    <m:A xmlns:m="http://example.json">
        <m:a>{a}</m:a>
        <m:b>{b}</m:b>
    </m:A>);

Similarly mc.setJSON() method can be used to set arbitrary JSON objects. 类似地, mc.setJSON()方法可用于设置任意JSON对象。

The only way to reliably convert json to xml and back again is via the use of type hints in the xml. 将json可靠地转换为xml并再次返回的唯一方法是通过在xml中使用类型提示。 the default converter does not do this. 默认转换器不会这样做。 it 1. drops everything after the first property 2. confuses single element lists with properties when going from xml to json 1.在第一个属性之后删除所有内容2.从xml到json时,将单个元素列表与属性混淆

i have reimplemented the transconversion classes using the json-util library, which converts the json to xml containing type hints as element attributes, to ensure no ambiguity. 我使用json-util库重新实现了transconversion类,它将json转换为包含类型提示作为元素属性的xml,以确保没有歧义。

in this way we can smart proxy (ie content route and mediate on transport and payload) for ALL json based rest services through WSO2 with no issues 通过这种方式我们可以通过WSO2为所有基于json的休息服务提供智能代理(即内容路由并调解传输和有效负载),没有任何问题

This solves the problem (I think camel does it this way by default). 这解决了这个问题(我认为骆驼默认这样做)。

Here is the pom file and code: 这是pom文件和代码:

place the jar into /repository/components/lib 将jar放入/ repository / components / lib

you must update the messageformatter and messagebuilder mappings for content type "application/json" in axis2.xml 您必须在axis2.xml中更新内容类型“application / json”的messageformatter和messagebuilder映射


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <name>wso2 json/xml converter</name>
    <groupId>x.y.z</groupId>
    <artifactId>wso2converter</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <jdk.version>1.6</jdk.version>
    </properties>

    <build>
        <finalName>wso2converter</finalName>
        <resources>
            <resource>
                <filtering>false</filtering>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${jdk.version}</source>
                    <target>${jdk.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-enforcer-plugin</artifactId>
                <version>1.0.1</version>
                <executions>
                    <execution>
                        <id>enforce-jdk</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>display-info</goal>
                            <goal>enforce</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <requireJavaVersion>
                                    <version>[${jdk.version},)</version>
                                </requireJavaVersion>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.3</version>
            <classifier>jdk15</classifier>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.ws.commons.axiom</groupId>
            <artifactId>axiom-api</artifactId>
            <version>1.2.13</version>
        </dependency>

        <dependency>
            <groupId>org.apache.axis2</groupId>
            <artifactId>axis2-kernel</artifactId>
            <version>1.6.2</version>
        </dependency>

        <dependency>
            <groupId>xom</groupId>
            <artifactId>xom</artifactId>
            <version>1.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.synapse</groupId>
            <artifactId>synapse-core</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.1.5</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.13</version>
            <!--scope>provided</scope-->
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

package a.b.wso2;

import java.io.InputStream;
import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import net.sf.json.xml.XMLSerializer;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.util.AXIOMUtil;
import org.apache.axis2.AxisFault;
import org.apache.axis2.builder.Builder;
import org.apache.axis2.context.MessageContext;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;


public class WsoJtoX implements Builder {

    Logger logger = Logger.getLogger("a.b.wso2converter");

    @Override
    public OMElement processDocument(InputStream is, String contentType,
            MessageContext messageContext) throws AxisFault {
        String jsonData = "";
        try {

            jsonData = IOUtils.toString(is,"UTF-8");


            String output = process(jsonData);

            OMElement e = AXIOMUtil.stringToOM(output);
            return e;


        } catch (Exception e) {
            logger.error("error converting json string " + jsonData, e);
            if (e instanceof AxisFault) {
                throw (AxisFault) e;
            }
            throw new AxisFault("(B"+counter+") error converting json to xml", e);
        }

    }

    static int counter=0;

    public String process(String jsonData) throws AxisFault {

        try {
            String tran = "__ns__";

            jsonData=jsonData.replace("\r", "").trim();
            //jsonData=jsonData.replace("\n", "");

            String decoded = (jsonData.replaceAll("\"([a-zA-Z0-9_]*)\\:([a-zA-Z0-9]*)\"(\\s*)(:)", "\"$1" + tran + "$2\"$3:"));

            counter++;

            if (logger.isDebugEnabled()) {
                logger.debug("\n>>>>> (B"+counter+") converting json\n " + jsonData + "\n====");
            }

            XMLSerializer serializer = new XMLSerializer();
            JSON json = JSONSerializer.toJSON(decoded);

            String xml = serializer.write(json);

            //add in the soap stuff
            StringBuilder sb = new StringBuilder();
            sb.append("<soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\" soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\"> <soap:Body>");
            sb.append(xml.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", ""));
            sb.append("</soap:Body></soap:Envelope>");

            if (logger.isDebugEnabled()) {
                logger.debug("\n==== (B"+counter+") to xml\n" + sb.toString()+"\n<<<<<");
            }

            return sb.toString();


        } catch (Exception e) {
            throw new AxisFault("(B"+counter+") error transforming json to xml", e);
        }

    }

}

package a.b.wso2;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import net.sf.json.JSON;

import net.sf.json.xml.XMLSerializer;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.util.AXIOMUtil;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.transport.MessageFormatter;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

public class WsoXtoJ implements MessageFormatter {

    Logger logger = Logger.getLogger("a.b.wso2converter");

    private static int counter=0;

    public String convert(String xData) {

        counter++;

            if (logger.isDebugEnabled()) {
                logger.debug("\n]]]]] (A"+counter+") converting xml\n " + xData + "\n-----");
            }


        try {
            String tran = "__ns__";
            XMLSerializer serializer = new XMLSerializer();
            OMElement e = AXIOMUtil.stringToOM(xData);
            OMElement b = (OMElement) e.getChildrenWithLocalName("Body").next();
            b = (OMElement) b.getChildElements().next();
            String xfrag = b.toStringWithConsume();
            String str = "";
            JSON j = serializer.read(xfrag);
            str = j.toString();
            String nstr = str.replaceAll("\"([a-zA-Z0-9_]+)" + tran + "([a-zA-Z0-9]+)\"(\\s*)(:)", "\"$1:$2\"$3:");  //", "\"$1:$2\"");

            if (logger.isDebugEnabled()) {
                logger.debug("\n----- (A"+counter+") to json\n" + nstr+"\n[[[[[");
            }

            return nstr;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public String formatSOAPAction(MessageContext msgCtxt, OMOutputFormat format,
            String soapActionString) {
        return null;
    }

    @Override
    public byte[] getBytes(MessageContext ctx, OMOutputFormat format)
            throws AxisFault {
        String env="";
        try {
            OMElement element = ctx.getEnvelope().getBody().getFirstElement();
            String payload = this.convert(element.toString());
            return payload.getBytes(format.getCharSetEncoding());
        } catch (UnsupportedEncodingException e) {
            logger.error("(A"+counter+") error converting xml to json "+ctx.getEnvelope().toString());
            throw AxisFault.makeFault(e);
        }
    }

    @Override
    public String getContentType(MessageContext msgCtxt, OMOutputFormat format,
            String soapActionString) {
        String contentType = (String) msgCtxt.getProperty(Constants.Configuration.CONTENT_TYPE);
        String encoding = format.getCharSetEncoding();
        if (contentType == null) {
            contentType = (String) msgCtxt.getProperty(Constants.Configuration.MESSAGE_TYPE);
        }
        if (encoding != null) {
            contentType += "; charset=" + encoding;
        }
        return contentType;
    }

    @Override
    public URL getTargetAddress(MessageContext msgCtxt, OMOutputFormat format,
            URL targetURL) throws AxisFault {
        return targetURL;
    }

    @Override
    public void writeTo(MessageContext msgCtxt, OMOutputFormat format,
            OutputStream out, boolean preserve) throws AxisFault {
        try {
            out.write(this.getBytes(msgCtxt, format));
            out.flush();
        } catch (IOException e) {
            throw AxisFault.makeFault(e);
        }
    }

}

I had the same problem. 我有同样的问题。

In my experience, the JSON parser for WSO2 ESB (based on Axis2-json) supports only a subset of JSON: 根据我的经验,WSO2 ESB的JSON解析器(基于Axis2-json)仅支持JSON的一个子集:

  1. The JSON has to start with "{", ie there can't be a JSONArray at the root. JSON必须以“{”开头,即根目录下不能有JSONArray。

  2. Only the first key-value pair will be considered. 仅考虑第一个键值对。 This is because JSON is mapped to XML-like datastructure, and XML must have a root, so the first key-value pair is considered as root. 这是因为JSON映射到类似XML的数据结构,并且XML必须具有根,因此第一个键值对被视为root。

  3. The value of the first key-value pair must not be an array. 第一个键值对的值不能是数组。 This because the converter has to know which XML tag should be used for each value: 这是因为转换器必须知道每个值应该使用哪个XML标记:

    eg: ... { "key": ["val1", "val2", ...]} -> <key>val1</key><key>val2</key>.... 例如:... {“key”:[“val1”,“val2”,...]} - > <key> val1 </ key> <key> val2 </ key> ....

I have the same problem here and want to find a fix for this. 我在这里有同样的问题,想找到一个解决方案。 My thoughts are to create a new JSONBuilder (the parser which builds the internal SOAP message construct) and the JSONFormatter (the serializer) to use a virtual root (eg { " root " : ... } ) to fake the parser. 我的想法是创建一个新的JSONBuilder(构建内部SOAP消息构造的解析器)和JSONFormatter(序列化器)来使用虚拟根(例如{“ root ”:...})伪造解析器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM