【问题标题】:Using Jettison to go from JSON to DOM in Java使用 Jettison 在 Java 中从 JSON 到 DOM
【发布时间】:2010-10-25 15:46:02
【问题描述】:

到目前为止,这是一个失败的故事,欢迎提出任何建议。我尝试了以下方法:

使用带有 Saxon 的 JAXP 到 XMLStreamReader 到文档

代码:

JSONObject obj = new JSONObject("{\"alice\":{\"bob\": \"a\"}}");
AbstractXMLStreamReader reader = new MappedXMLStreamReader(obj);

StAXSource source = new StAXSource(reader);
Document document = XMLUtils.createDocument();
DOMResult result = new DOMResult(document);
Transformer identity = TransformerUtils.getIdentityTransformer();
identity.transform(source, result);
result.getNode();

这会失败,因为我们使用的 Saxon 转换器不支持 StAXSource。例外是:

org.orbeon.saxon.trans.DynamicError: A source of type javax.xml.transform.stax.StAXSource is not supported in this environment
    org.orbeon.saxon.event.Sender.send(Sender.java:185)
    org.orbeon.saxon.IdentityTransformer.transform(IdentityTransformer.java:29)
    org.orbeon.oxf.xml.TransformerWrapper.transform(TransformerUtils.java:597)
    org.apache.jsp.gaga_jsp._jspService(gaga_jsp.java:93)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:328)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:315)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

使用带有 Xalan 的 JAXP 到文档的 XMLStreamReader

代码:

JSONObject obj = new JSONObject("{\"alice\":{\"bob\": \"a\"}}");
AbstractXMLStreamReader reader = new MappedXMLStreamReader(obj);

StAXSource source = new StAXSource(reader);
Document document = XMLUtils.createDocument();
DOMResult result = new DOMResult(document);
Transformer identity = orbeon.apache.xalan.processor.TransformerFactoryImpl.newInstance().newTransformer();
identity.transform(source, result);
result.getNode();

Xalan 2.5.1(我们正在使用的版本)会失败。最新版本是 2.7.1,也许他们在该版本中添加了对 StAXSource 的支持。

javax.xml.transform.TransformerException: Can't transform a Source of type javax.xml.transform.stax.StAXSource
    orbeon.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:372)
    org.apache.jsp.gaga_jsp._jspService(gaga_jsp.java:82)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:328)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:315)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

使用 XMLEventWriter 和 DOMResult 的 XMLStreamReader 到文档

代码:

JSONObject obj = new JSONObject("{\"alice\":{\"bob\": \"a\"}}");
AbstractXMLStreamReader streamReader = new MappedXMLStreamReader(obj);
XMLInputFactory readerFactory = XMLInputFactory.newInstance();
XMLEventReader eventReader = readerFactory.createXMLEventReader(streamReader);

Document document = XMLUtils.createDocument();
DOMResult result = new DOMResult(document);
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
XMLEventWriter eventWriter = outputFactory.createXMLEventWriter(result);
eventWriter.add(eventReader);
eventWriter.close();

result.getNode();

这会导致 Xerces 中的 NPE:

java.lang.NullPointerException
    orbeon.apache.xerces.dom.CoreDocumentImpl.setXmlVersion(CoreDocumentImpl.java:850)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    java.lang.reflect.Method.invoke(Method.java:597)
    com.sun.xml.internal.stream.writers.XMLDOMWriterImpl.writeStartDocument(XMLDOMWriterImpl.java:583)
    com.sun.xml.internal.stream.writers.XMLEventWriterImpl.add(XMLEventWriterImpl.java:96)
    com.sun.xml.internal.stream.writers.XMLEventWriterImpl.add(XMLEventWriterImpl.java:72)
    org.apache.jsp.gaga_jsp._jspService(gaga_jsp.java:95)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:328)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:315)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

使用 XMLEventWriter 和 Writer 将 XMLStreamReader 转换为文档

代码:

JSONObject obj = new JSONObject("{\"alice\": {\"bob\": \"a\"}}");
AbstractXMLStreamReader streamReader = new MappedXMLStreamReader(obj);
XMLInputFactory readerFactory = XMLInputFactory.newInstance();
XMLEventReader eventReader = readerFactory.createXMLEventReader(streamReader);

StringWriter stringWriter = new StringWriter();
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
XMLEventWriter eventWriter = outputFactory.createXMLEventWriter(stringWriter);
eventWriter.add(eventReader);
eventWriter.close();

out.print(stringWriter.toString());

在 Java 5 中,它会寻找找不到的 com.bea.xml.stream.MXParserFactory

javax.xml.stream.FactoryConfigurationError: Provider com.bea.xml.stream.MXParserFactory not found
    javax.xml.stream.FactoryFinder.newInstance(FactoryFinder.java:72)
    javax.xml.stream.FactoryFinder.find(FactoryFinder.java:178)
    javax.xml.stream.FactoryFinder.find(FactoryFinder.java:92)
    javax.xml.stream.XMLInputFactory.newInstance(XMLInputFactory.java:136)
    org.apache.jsp.gaga_jsp._jspService(gaga_jsp.java:79)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:328)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:315)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

使用 Java 6,它会导致 Sun 的 XMLEventAllocatorImpl 中的 NPE:

java.lang.NullPointerException
    com.sun.xml.internal.stream.events.XMLEventAllocatorImpl.getXMLEvent(XMLEventAllocatorImpl.java:82)
    com.sun.xml.internal.stream.events.XMLEventAllocatorImpl.allocate(XMLEventAllocatorImpl.java:55)
    com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent(XMLEventReaderImpl.java:86)
    com.sun.xml.internal.stream.writers.XMLEventWriterImpl.add(XMLEventWriterImpl.java:72)
    org.apache.jsp.gaga_jsp._jspService(gaga_jsp.java:85)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:328)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:315)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

使用 BadgerFishDOMDocumentParser

代码:

ByteArrayInputStream bais = new ByteArrayInputStream("{\"alice\": {\"bob\": \"a\"}}".getBytes());
Document resDOM = new BadgerFishDOMDocumentParser().parse(bais);

这个在 Sun 的XMLEventAllocatorImpl 中给了我们一个 NPE:

java.lang.NullPointerException
    com.sun.xml.internal.stream.events.XMLEventAllocatorImpl.getXMLEvent(XMLEventAllocatorImpl.java:82)
    com.sun.xml.internal.stream.events.XMLEventAllocatorImpl.allocate(XMLEventAllocatorImpl.java:55)
    com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent(XMLEventReaderImpl.java:86)
    com.sun.xml.internal.stream.writers.XMLEventWriterImpl.add(XMLEventWriterImpl.java:72)
    org.codehaus.jettison.AbstractDOMDocumentParser.parse(AbstractDOMDocumentParser.java:66)
    org.apache.jsp.gaga_jsp._jspService(gaga_jsp.java:79)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:328)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:315)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

【问题讨论】:

    标签: java xml json dom jettison


    【解决方案1】:

    JSON 不是 XML - 看起来您正在尝试使用 XML 解析器解析 JSON 对象? 不过,我可能误解了你的意思。

    【讨论】:

    • @RedMage,我不想将 JSON 解析为 XML。我正在尝试使用解析 JSON 并将其转换为 XML 的 Jettison 库。你可以阅读更多关于 Jettison 的信息:jettison.codehaus.org
    【解决方案2】:

    不,出于某种原因,我认为 Xalan 不支持 Stax。 Saxon 可以,所以你可以试试吗?

    但如果没有,也许您应该使用 link text 从 Stax 构建一个 DOM 树,就像 this article 解释的那样? Xalan 确实接受 DOM 源作为输入。

    【讨论】:

      【解决方案3】:

      我也遇到了这个问题,并且经历了和 OP 一样的挫败感。在某处的woodstox 邮件列表中提到了这种行为作为错误。但是,我能够开发一个解决方案。我编写了一个非常基本的 XMLEventReader,它包装了一个 XMLStreamReader,它做得很好。两个重要说明: 1) 此代码按原样提供;具体来说,除了我自己的有限使用之外,我还没有彻底测试过它,2)这个问题在互联网上的其他地方几乎不存在,以及这似乎是 Jettison 应该执行的一个相对基本的操作,强烈建议我,我们正在做一些根本错误的事情,这个解决方案不应该是必要的。用你自己的判断。

      首先,这是一个工作的 XMLEventReader:

      import java.util.LinkedList;
      import java.util.Queue;
      
      import javax.xml.stream.XMLEventReader;
      import javax.xml.stream.XMLStreamException;
      import javax.xml.stream.XMLStreamReader;
      import javax.xml.stream.events.XMLEvent;
      
      import com.sun.xml.internal.stream.events.AttributeImpl;
      import com.sun.xml.internal.stream.events.CharacterEvent;
      import com.sun.xml.internal.stream.events.CommentEvent;
      import com.sun.xml.internal.stream.events.DTDEvent;
      import com.sun.xml.internal.stream.events.EndDocumentEvent;
      import com.sun.xml.internal.stream.events.EndElementEvent;
      import com.sun.xml.internal.stream.events.NamespaceImpl;
      import com.sun.xml.internal.stream.events.ProcessingInstructionEvent;
      import com.sun.xml.internal.stream.events.StartDocumentEvent;
      import com.sun.xml.internal.stream.events.StartElementEvent;
      
      public class WorkingXMLEventReader implements XMLEventReader {
      
          private final XMLStreamReader streamReader;
          private final Queue<XMLEvent> eventQueue = new LinkedList<XMLEvent>();
      
          public WorkingXMLEventReader (XMLStreamReader streamReader) {
              this.streamReader = streamReader;
          }
      
          @Override public Object next () {
              try {
                  return nextEvent();
              } catch (XMLStreamException x) {
                  return null;
              }
          }
      
          @Override public void remove () {
              throw new UnsupportedOperationException("WorkingXMLEventReader iterator interface does not support remove()");
          }
      
          @Override public void close () throws XMLStreamException {
              streamReader.close();
              eventQueue.clear();
          }
      
          @Override public String getElementText () throws XMLStreamException {
              return streamReader.getElementText();
          }
      
          @Override public Object getProperty (String key) throws IllegalArgumentException {
              return streamReader.getProperty(key);
          }
      
          @Override public boolean hasNext () {
              try {
                  return !eventQueue.isEmpty() || streamReader.hasNext();
              } catch (XMLStreamException x) {
                  return false;
              }
          }
      
          @Override public XMLEvent nextEvent () throws XMLStreamException {
              if (eventQueue.isEmpty())
                  parseEvents(eventQueue, streamReader, streamReader.next());
              return eventQueue.remove();
          }
      
          @Override public XMLEvent nextTag () throws XMLStreamException {
              if (eventQueue.isEmpty())
                  parseEvents(eventQueue, streamReader, streamReader.nextTag());
              return eventQueue.remove();        
          }
      
          @Override public XMLEvent peek () throws XMLStreamException {
              return eventQueue.peek();
          }
      
          protected static void parseEvents (Queue<XMLEvent> events, XMLStreamReader reader, int type) {
              switch (type) {
              case XMLEvent.START_ELEMENT: 
                  events.add(new StartElementEvent(reader.getName()));
                  break;
              case XMLEvent.END_ELEMENT: 
                  events.add(new EndElementEvent(reader.getName()));
                  break;
              case XMLEvent.CDATA:
                  events.add(new CharacterEvent(reader.getText(), true, false));
                  break;
              case XMLEvent.SPACE:
                  events.add(new CharacterEvent(reader.getText(), false, true));
                  break;
              case XMLEvent.CHARACTERS: 
                  events.add(new CharacterEvent(reader.getText(), false, false));
                  break;
              case XMLEvent.ATTRIBUTE:
                  for (int n = 0; n < reader.getAttributeCount(); ++ n) {
                      AttributeImpl attr = new AttributeImpl(reader.getAttributePrefix(n), 
                              reader.getAttributeNamespace(n), reader.getAttributeLocalName(n), 
                              reader.getAttributeValue(n), reader.getAttributeType(n));
                      events.add(attr);
                  }
                  break;
              case XMLEvent.NAMESPACE:
                  for (int n = 0; n < reader.getNamespaceCount(); ++ n) {
                      NamespaceImpl ns = new NamespaceImpl(reader.getNamespacePrefix(n), 
                              reader.getNamespaceURI(n));
                      events.add(ns);
                  }
                  break;
              case XMLEvent.PROCESSING_INSTRUCTION:
                  events.add(new ProcessingInstructionEvent(reader.getPITarget(), reader.getPIData()));
                  break;
              case XMLEvent.COMMENT:
                  events.add(new CommentEvent(reader.getText()));
                  break;
              case XMLEvent.START_DOCUMENT:
                  events.add(new StartDocumentEvent(reader.getEncoding(), reader.getVersion()));
                  break;
              case XMLEvent.END_DOCUMENT:
                  events.add(new EndDocumentEvent());
                  break;
              case XMLEvent.DTD:
                  events.add(new DTDEvent(reader.getText()));
                  break;
              }   
          }
      
      }
      

      接下来,这里是如何将它用于 OP 的示例:

      XMLStreamReader streamReader = new MappedXMLStreamReader(new JSONObject("{\"alice\":{\"bob\": \"a\"}}"));
      XMLEventReader eventReader = new WorkingXMLEventReader(streamReader);
      
      Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
      XMLEventWriter eventWriter = XMLOutputFactory.newInstance().createXMLEventWriter(new DOMResult(document));
      eventWriter.add(eventReader);
      eventWriter.close();
      
      // test
      Source testSource = new DOMSource(document);
      Result testResult = new StreamResult(System.out);
      TransformerFactory.newInstance().newTransformer().transform(testSource, testResult);
      

      输出应该是这样的:

      <?xml version="1.0" encoding="UTF-8" standalone="no"?><alice><bob>a</bob></alice>
      

      希望对某人有所帮助。

      【讨论】:

        猜你喜欢
        • 2018-06-30
        • 2013-12-25
        • 2013-11-19
        • 2012-02-01
        • 2013-03-03
        • 2011-05-17
        • 2015-06-06
        • 2013-03-02
        相关资源
        最近更新 更多