Recursive Nodes In XML Generated By JBPM 7

≯℡__Kan透↙ 提交于 2021-02-05 07:57:07

问题


The following XML is what JBPM spits out for variables used in a process. In other words, it is machine generated. I have tried for several hours to parse this with Jackson and has gone nowhere. Below you can find Java classes I am using. I am attaching a typical serializer that I have used with various debugging in eclipse without luck.

XML:

<map-type>
    <entries>
        <entry>
            <key>document</key>
            <value xsi:type="jaxbMap" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                <entries>
                    <entry>
                        <key>org.jbpm.document.service.impl.DocumentImpl</key>
                        <value xsi:type="jaxbMap">
                            <entries>
                                <entry>
                                    <key>identifier</key>
                                    <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">
                                        fc3a87c9-d22c-449b-b772-756fcc9a385d
                                    </value>
                                </entry>
                                <entry>
                                    <key>size</key>
                                    <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">1186</value>
                                </entry>
                                <entry>
                                    <key>name</key>
                                    <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">
                                        dmv-registration.txt
                                    </value>
                                </entry>
                                <entry>
                                    <key>link</key>
                                    <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">
                                        fc3a87c9-d22c-449b-b772-756fcc9a385d
                                    </value>
                                </entry>
                                <entry>
                                    <key>attributes</key>
                                </entry>
                                <entry>
                                    <key>lastModified</key>
                                    <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">Mon Mar 09
                                        18:19:25 PDT 2020
                                    </value>
                                </entry>
                                <entry>
                                    <key>content</key>
                                    <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema"></value>
                                </entry>
                            </entries>
                        </value>
                    </entry>
                    <entry>
                        <key>uploader_name</key>
                        <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">murthy</value>
                    </entry>
                    <entry>
                        <key>uploader_mail</key>
                        <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">gandikotam@gmail.com
                        </value>
                    </entry>
                </entries>
            </value>
        </entry>
        <entry>
            <key>initiator</key>
            <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">kieserver
            </value>
        </entry>
    </entries>
</map-type>

Java classes:

package com.murthy;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

public class ProcessVariableMapType {
    @JsonProperty("entries")
    @JsonDeserialize(using = CustomEntriesDeserializer.class)   
    List<ProcessVariableEntries> entries;

    public List<ProcessVariableEntries> getEntries() {
        return entries;
    }

    public void setEntries(List<ProcessVariableEntries> entries) {
        this.entries = entries;
    }



}
package com.murthy;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

@JsonIgnoreProperties(ignoreUnknown = true)

public class ProcessVariableEntries {
    @JsonProperty("entry")
    @JsonDeserialize(using = CustomEntryDeserializer.class) 
    List<ProcessVariableEntry> processVariableEntries;

    public List<ProcessVariableEntry> getProcessVariableEntries() {
        return processVariableEntries;
    }

    public void setProcessVariableEntries(List<ProcessVariableEntry> processVariableEntries) {
        this.processVariableEntries = processVariableEntries;
    }

}

package com.murthy;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

@JsonIgnoreProperties(ignoreUnknown = true)

public class ProcessVariableEntry {
    @JsonProperty("key")
    List<String> key;
    @JsonProperty("value")

    @JsonDeserialize(using = CustomListDeserializer.class)  
    List<ProcessVariableStringValue> value;
    public List<String> getKey() {
        return key;
    }
    public void setKey(List<String> key) {
        this.key = key;
    }
    public List<ProcessVariableStringValue> getValue() {
        return value;
    }
    public void setValue(List<ProcessVariableStringValue> value) {
        this.value = value;
    }



}

package com.murthy;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

@JsonIgnoreProperties(ignoreUnknown = true)

public class ProcessVariableStringValue extends ProcessVariableParent{
    @JsonProperty("entries")
//  @JsonDeserialize(using = CustomEntriesDeserializer.class)
    List<ProcessVariableEntries> entries;
    @JsonProperty("key")
    String key;
    @JsonProperty("value")
    String value;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }



    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public List<ProcessVariableEntries> getEntries() {
        return entries;
    }

    public void setEntries(List<ProcessVariableEntries> entries) {
        this.entries = entries;
    }




}


package com.murthy;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

public class CustomEntriesDeserializer extends JsonDeserializer<List<ProcessVariableEntries>> {

//    public CustomListDeserializer() {
//        this(null);
//    }

//    public CustomListDeserializer(Class<?> vc) {
//        super(vc);
//    }

//    @Override
    public List<ProcessVariableEntries>  deserialize(
      JsonParser jp, 
      DeserializationContext context) 
      throws IOException, JsonProcessingException {
//      ObjectCodec oc = jsonparser.getCodec();
        JsonNode node = jp.getCodec().readTree(jp);
      Iterator<JsonNode> iter = node.elements();
        while(iter.hasNext()) {
            JsonNode n = iter.next();
            System.out.println("json node" + n);
        }
//       ObjectMapper mapper = (ObjectMapper) jp.getCodec();
//      Map<String, Object> m=mapper.readValue(jp, new TypeReference<Map<String, Object>>() {});
//      for (Map.Entry<String, Object> me : m.entrySet()) {
//          System.out.println("key=" + me.getKey() + " val=" + me.getValue());
//      }

//         ObjectNode root = (ObjectNode) mapper.readTree(jp);
          JacksonXmlModule module = new JacksonXmlModule();
            module.setDefaultUseWrapper(false);
            XmlMapper xmlMapper = new XmlMapper(module);
            ProcessVariableEntries pve = xmlMapper.readValue(jp,ProcessVariableEntries.class);
//       ProcessVariableEntries pve = mapper.readValue(jp, ProcessVariableEntries.class);
//      List<ProcessVariableEntries> pveList = mapper.readValues(jp, ProcessVariableEntries.class);
         List<ProcessVariableEntries> pveList = new ArrayList<ProcessVariableEntries>();
         pveList.add(pve);
//         System.out.println("root=" + root);
//       ProcessVariableEntry pve2 = null;
//       pve2=mapper.readValue(jp, ProcessVariableEntry.class);
//       ProcessVariableStringValue pvs=null;
//       if (pve2 == null) {
//           pvs = mapper.readValue(jp, ProcessVariableStringValue.class);
//       }
//       if (pvs == null) {
//           
//       }
         System.out.println(pveList);
         if (1==1)
             return pveList;
         Class<? extends ProcessVariableParent> instanceClass = null;
         if(1==2) {
             System.out.println("in proc var");
             instanceClass = ProcessVariableValue.class;
         } else { 
             System.out.println("in proc var string");
             instanceClass = ProcessVariableStringValue.class;
         }   
         if (instanceClass == null){
             return null;
         }
         System.out.println("instance found!" );
//         Iterator<JsonNode> iter = root.elements();
//      while(iter.hasNext()) {
//          JsonNode n = iter.next();
//          System.out.println("json node" + n);
//      }
         return null;// mapper.readValue(jp, instanceClass );
//      Map<String, Object> m=oc.readValue(jsonparser, new TypeReference<Map<String, Object>>() {});
//      for (Map.Entry<String, Object> me : m.entrySet()) {
//          System.out.println("key=" + me.getKey() + " val=" + me.getValue());
//      }
//      if (jsonparser.getCodec().readTree(jsonparser) instanceof ObjectNode)
//          node = oc.readTree(jsonparser);
//          else
//              s = jsonparser.getCodec().readTree(jsonparser).toString();
//      System.out.println("code=" + jsonparser.getCodec().readTree(jsonparser));
//      JsonNode node1 = oc.readTree(jsonparser);
//      System.out.println("node1=" + node1 + node1.get(2) + " " + node1.get(1));
        /*
        Iterator<JsonNode> iter = node1.get(2).elements();
        while(iter.hasNext()) {
            JsonNode node = iter.next();
            System.out.println("json node" + node);
        }
        */
//      String type = (String)m.get("type");
//      System.out.println("returning new process variable value");
//      ProcessVariableValue pvv = new ProcessVariableValue();
//      pvv.setValue(m == null ? ""  : (String)m.get(""));
//        return pvv;
    }
}

回答1:


If XML payload contains recursive structure you need to build similar Java POJO model classes. All values could extends the same interface or abstract class. Take a look on below example model:

@JsonTypeName("map-type")
class Root {

    @JacksonXmlProperty(localName = "entry")
    @JacksonXmlElementWrapper(localName = "entries")
    private List<Entry> entries;

    public List<Entry> getEntries() {
        return entries;
    }

    public void setEntries(List<Entry> entries) {
        this.entries = entries;
    }
}

@JsonTypeInfo(include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type", use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
        @JsonSubTypes.Type(name = "xs:string", value = StringType.class),
        @JsonSubTypes.Type(name = "jaxbMap", value = MapType.class)
})
interface JBPMValue {
}

class StringType implements JBPMValue {
    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @JsonAnySetter
    public void anySetter(String key, String value) {
        this.value = value.trim();
    }

    @Override
    public String toString() {
        return value;
    }
}

class MapType implements JBPMValue {

    @JacksonXmlProperty(localName = "entry")
    @JacksonXmlElementWrapper(localName = "entries")
    private List<Entry> entries;

    public List<Entry> getEntries() {
        return entries;
    }

    public void setEntries(List<Entry> entries) {
        this.entries = entries;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("MapType{");
        sb.append(System.lineSeparator());
        entries.forEach(e -> sb.append(e.toString()).append(System.lineSeparator()));
        sb.append('}');
        return sb.toString();
    }
}

class Entry {
    private String key;
    private JBPMValue value;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public JBPMValue getValue() {
        return value;
    }

    public void setValue(JBPMValue value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "{" + key + "=" + value + "}";
    }
}

As you can see I used @JsonTypeInfo and @JsonSubTypes to define POJO classes for each type in XML. @JacksonXmlProperty and @JacksonXmlElementWrapper annotation are used to represent wrapped collections.

Now, we can create simple example how to use it:

import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;

import java.io.File;
import java.util.List;

public class XmlMapperApp {

    public static void main(String... args) throws Exception {
        File xmlFile = new File("./resource/test.xml").getAbsoluteFile();

        XmlMapper mapper = XmlMapper.xmlBuilder().build();
        Root root = mapper.readValue(xmlFile, Root.class);
        root.getEntries().forEach(System.out::println);
    }
}

Above code for your XML payload prints:

{document=MapType{
{org.jbpm.document.service.impl.DocumentImpl=MapType{
{identifier=fc3a87c9-d22c-449b-b772-756fcc9a385d}
{size=1186}
{name=dmv-registration.txt}
{link=fc3a87c9-d22c-449b-b772-756fcc9a385d}
{attributes=null}
{lastModified=Mon Mar 09
                                        18:19:25 PDT 2020}
{content=null}
}}
{uploader_name=murthy}
{uploader_mail=gandikotam@gmail.com}
}}
{initiator=kieserver}


来源:https://stackoverflow.com/questions/60678696/recursive-nodes-in-xml-generated-by-jbpm-7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!