WSO2 ESB не удалось преобразовать полные данные JSON в XML

Я строю POC. И я создал пропуск через прокси-сервис для Google Plus. Без использования какой-либо прокси-службы я получаю это мой вывод:

 {
   "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":"u003cbu003ehie, abhishek - ma full name u003c/bu003eu003cdivu003eu003cbu003em a DANCER ,u003c/bu003eu003c/divu003eu003cdivu003eu003cbu003ei luv ma dancing .u003c/bu003eu003c/divu003eu003cdivu003eu003cbu003ei care ma dancing ,u003c/bu003eu003c/divu003eu003cdivu003eu003cbu003ei jus hv a gr8 thng in me dats ma dancing.u003c/bu003eu003c/divu003e",
   "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"
      }
   ]
}

но когда я пытаюсь сделать то же самое, используя простой проход через службу, я получаю только :

{
   "kind":"plus#person"
}

Я прочитал на сайте wso2esb, что у них была ошибка, и объяснение, данное для устранения ошибки, заключалось в том, что полученные данные json не были в правильном формате. Но как мне теперь решить эту проблему? Я имею в виду их в любом случае я могу манипулировать данными json, прежде чем esb преобразует их в данные json.

4 ответов


мы решили эту проблему в последней версии ESB (версия 4.5.0). По умолчанию он поставляется с JSONMessageFormatter/JSONBuilder, который может обрабатывать полезные нагрузки JSON с несколькими ключами.

мы также придумали другое решение для обработки потоков сообщений, которые включают различные типы преобразований JSON XML (или JSON JSON). JSONStreamBuilder и JSONStreamFormatter может использоваться для реализации таких сценариев с посредником "сценарий". Посмотрите на образец #441 в ESB 4.5.0.

для запуска образца #441;

  • добавить JSONStreamBuilder и JSONStreamFormatter как строитель и форматеру для JSON в хранилище/конф/в axis2/в axis2.xml-файл
  • Развернуть SimpleStockQuoteService
  • запустите образец axis2server
  • запустите клиент JSON с помощью'ant newjsonclient'

Это одно из ограничений текущего axis2 JSON builder/formatter. В настоящее время мы работаем над новой парой builder/formatter для JSON, которая не преобразует JSON XML. Вместо этого он (builder) хранит сообщение JSON как поток, и посредник скрипта может использоваться для создания объекта JSON из этого потока. Например, если мы отправим {"a" : "x", "b" : "y"} в качестве запроса в ESB, мы можем манипулировать этим запросом как объектом JSON с javascript.

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>);

аналогично mc.setJSON() метод может использоваться для установки произвольных объектов JSON.


единственный способ надежно преобразовать json в xml и обратно - это использование подсказок типа в xml. конвертер по умолчанию этого не делает. он 1. отбрасывает все после первого свойства 2. путает списки отдельных элементов со свойствами при переходе от xml к JSON

Я повторно реализовал классы трансконверсии с помощью библиотеки JSON-util, которая преобразует json в xml, содержащий подсказки типов в качестве атрибутов элементов, чтобы обеспечить отсутствие двусмысленности.

в этом способ, которым мы можем smart proxy (т. е. content route и посредничать на транспорте и полезной нагрузке) для всех служб rest на основе json через WSO2 без проблем

Это решает проблему (я думаю, что camel делает это таким образом по умолчанию).

вот файл pom и код:

поместите банку в / репозиторий / компоненты / lib

необходимо обновить сопоставления messageformatter и messagebuilder для типа контента "application/ json" в в axis2.в XML


<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*)(:)", "\"" + tran + "\":"));

            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*)(:)", "\":\":");  //", "\":\"");

            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);
        }
    }

}

У меня была та же проблема.

по моему опыту, парсер JSON для WSO2 ESB (основанный на Axis2-json) поддерживает только подмножество JSON:

  1. JSON должен начинаться с " { " , т. е. в корне не может быть JSONArray.

  2. будет рассмотрена только первая пара ключ-значение. Это связано с тем, что JSON сопоставляется с XML-подобной структурой данных, а XML должен иметь корень, поэтому первая пара ключ-значение рассматривается как корень.

  3. значение первой пары ключ-значение не должно быть массивом. Это потому, что конвертер должен знать, какой XML-тег должен использоваться для каждого значения:

    например: ... { "ключ": ["val1", "val2", ...]}- >val1 val2....

У меня такая же проблема вот и хочу найти исправление для этого. Мои мысли-создать новый jsonbuilder (парсер, который строит внутреннюю конструкцию сообщения SOAP) и Jsonformatter (сериализатор) для использования виртуального корня (например, {"root" : ... }) подделать парсер.