Рекурсивные узлы в XML, сгенерированные JBPM 7 - PullRequest
1 голос
/ 14 марта 2020

Следующее XML - это то, что JBPM выплевывает для переменных, используемых в процессе. Другими словами, это машина, созданная. Я несколько часов пытался разобрать это с Jackson и никуда не делся. Ниже вы можете найти Java классов, которые я использую. Я прилагаю типичный сериализатор, который я использовал для различных отладок в затмении без удачи.

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 классы:

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 Ответ

1 голос
/ 14 марта 2020

Если XML полезная нагрузка содержит рекурсивную структуру, вам нужно создать аналогичные Java POJO классовые модели. Все значения могут расширяться одинаково interface или abstract class. Взгляните на пример модели ниже:

@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 + "}";
    }
}

Как вы можете видеть, я использовал @JsonTypeInfo и @JsonSubTypes, чтобы определить POJO классы для каждого типа в XML. Аннотации @JacksonXmlProperty и @JacksonXmlElementWrapper используются для представления упакованных коллекций.

Теперь мы можем создать простой пример его использования:

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

Над кодом для вашей XML полезной нагрузки отпечатки:

{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}
...