WSO2 ESB incapable de convertir des données JSON complètes en XML

je construis un POC. Et j'ai créé un service proxy pass through pour Google Plus. Sans utiliser aucun service proxy, je reçois ceci est mon résultat:

 {
   "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"
      }
   ]
}

mais quand j'essaye de faire la même chose en utilisant un service de passage simple je reçois seulement :

{
   "kind":"plus#person"
}

j'ai lu sur le site wso2esb qu'ils avaient un bug et l'explication donnée pour résoudre le bug était que les données json reçues n'étaient pas dans le format approprié. Mais maintenant, comment puis-je résoudre le problème. Je veux dire, c'est leur tout je peux manipuler les données json avant que l'esb les convertisse en données json.

7
demandé sur tk_ 2012-05-25 11:31:51

4 réponses

nous avons résolu ce problème dans la dernière version de ESB (version 4.5.0). Par défaut, il est livré avec JSONMessageFormatter/JSONBuilder qui peut gérer les charges utiles JSON avec plusieurs clés.

nous avons aussi trouvé une autre solution pour gérer les flux de messages qui impliquent différents types de conversions JSON <--> XML (ou JSON <--> JSON). JSONStreamBuilder et JSONStreamFormatter peut être utilisé pour implémenter de tels scénarios avec le médiateur 'script'. Jetez un coup d'oeil à l'échantillon n ° 441 de L'ESB. 4.5.0.

Pour exécuter un exemple de #441;

  • Ajouter JSONStreamBuilder et JSONStreamFormatter en tant que constructeur et formateur pour l'JSON dans le repository/conf/axis2/axis2.fichier xml
  • Déployez SimpleStockQuoteService
  • Démarrer l'exemple de axis2server
  • exécuter le client JSON avec'ant newjsonclient'
5
répondu udeshike 2012-09-11 07:38:08

C'est l'une des limitations de l'actuel JSON builder/formatter axis2. Nous travaillons actuellement sur une nouvelle paire de builder/formatter pour JSON qui ne convertit pas JSON <-> XML. Au lieu de cela, it(builder) stocke le message JSON comme un flux et le script mediator peut être utilisé pour construire un objet JSON à partir de ce flux. Par exemple, si nous envoyons {"a" : "x", "b" : "y"} comme requête, au sein de L'ESB, nous pouvons manipuler cette requête comme un objet JSON avec 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>);

Même mc.setJSON() la méthode peut être utilisée pour définir des objets JSON arbitraires.

3
répondu udeshike 2012-05-31 08:30:18

la seule façon de convertir de manière fiable JSON en xml et de revenir est par l'utilisation d'indices de type dans le xml. le convertisseur par défaut ne fait pas cela. il 1. laisse tout tomber après la première propriété 2. confond les listes d'éléments simples avec les propriétés quand on passe de xml à json

j'ai réimplémenté les classes transconversion à l'aide de la bibliothèque json-util, qui convertit le JSON en xml contenant des indices de type comme attributs d'élément, pour éviter toute ambiguïté.

de cette façon nous pouvons Smart proxy (i.e. content route and mediate on transport and payload) pour tous les services de repos basés sur json via WSO2 sans problèmes

cela résout le problème (je pense que camel le fait de cette façon par défaut).

Voici le fichier pom et le code:

placez le pot dans /repository/composants/lib

vous devez mettre à jour les mappages messageformatter et messagebuilder pour le type de contenu "application / json" dans 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);
        }
    }

}
3
répondu john 2012-09-28 07:11:42

j'ai eu le même problème.

D'après mon expérience, L'analyseur JSON pour WSO2 ESB (basé sur Axis2-json) ne supporte qu'un sous-ensemble de JSON:

  1. le JSON doit commencer par " { " , c'est-à-dire qu'il ne peut pas y avoir de JSONArray à la racine.

  2. la première paire clé-valeur sera considérée. Ceci est dû au fait que JSON est mappé à une structure de données de type XML, et que XML doit avoir une racine, de sorte que la première paire de clés est considérée comme racine.

  3. la valeur de La première paire clé-valeur ne doit pas être un tableau. Ceci parce que le convertisseur doit savoir quelle balise XML doit être utilisée pour chaque valeur:

    par exemple: ... {"key": ["val1"," val2",...]}- >val1val2 < /key>....

j'ai le même problème ici, et que vous voulez trouver un correctif pour cela. Mes pensées sont de créer un nouveau JSONBuilder (l'analyseur qui construit la construction de message SOAP interne) et le JSONFormatter (le serializer) pour utiliser une racine virtuelle (par exemple {"racine":... } ) pour le faux de l'analyseur.

2
répondu erny 2012-05-25 16:38:16