5

我使用使用 JAXB 创建的数据模型,从中我可以直接生成 XML

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\
<metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#" xmlns:ext="http://musicbrainz.org/ns/ext#-2.0">
<artist-list offset="0" count="1">
   <artist ext:score="100" type="Group" id="4302e264-1cf0-4d1f-aca7-2a6f89e34b36">       
       <name>Farming Incident</name>
       <ipi-list>
          <ipi>1001</ipi>
       </ipi-list>
   </artist>
</artist-list>
</metadata>

在 Jersey 的帮助下,还使用自然表示法生成 JSON

"artist-list":
    {"offset":0,
     "count":1,
     "artist":[
         {"score":"100",
          "type":"Group",
          "id":"4302e264-1cf0-4d1faca7-2a6f89e34b36",
          "name":"Farming Incident",
          "ipi-list":
              {
                  "ipi":[
                       "1001"
                    ]
             }
          }]
     }

Xml很好,json几乎很好,除了因为Json直接支持具有ipi-list和artist-list等元素的数组似乎不是很json,是否可以从我的模型中生成更多json之类的json?

请求的附加信息json 是使用 JAXB 和 Jersey 从此 MMD 模式 http://svn.musicbrainz.org/mmd-schema/trunk/brainz-mmd2-jaxb/src/main/resources/musicbrainz_mmd-2.0.xsd生成的,见 http://svn.musicbrainz.org/search_server/trunk/servlet/src/main/java/org/musicbrainz/search/servlet/mmd2/ResultsWriter.javahttp://svn.musicbrainz.org/search_server/trunk /servlet/src/main/java/org/musicbrainz/search/servlet/mmd2/ArtistWriter.java

关键是我希望能够以最小的麻烦从一个模式生成 Json 和 XML,但显然 Json 看起来不正确,所以我正在寻找一种改进它的方法(我真的没有任何经验我自己的json)

4

5 回答 5

3

注意: 我是EclipseLink JAXB (MOXy)负责人,也是JAXB (JSR-222)专家组的成员。

您可以利用 EclipseLink JAXB (MOXy) 中的 JSON 绑定和外部映射文档来支持您的用例。

外部映射文件 (oxml.xml)

您可以使用@XmlPath(".")MOXy 中的扩展来展平对象模型的某些部分。指定路径"."告诉 MOXy 将引用的对象包含在父节点中。

<?xml version="1.0"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="forum10699038">
    <java-types>
        <java-type name="Metadata">
            <java-attributes>
                <xml-element java-attribute="artistList" xml-path="."/>
            </java-attributes>
        </java-type>
        <java-type name="Artist">
            <java-attributes>
                <xml-element java-attribute="ipiList" xml-path="."/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

jaxb.properties

要将 MOXy 指定为您的 JAXB 提供程序,您需要添加一个jaxb.properties在与您的域模型相同的包中调用的文件,其中包含以下条目。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

演示

下面的代码从您的 XML 文档填充对象模型,然后编组为 JSON。它演示了如何利用外部映射文件并将 MOXy 置于 JSON 模式。

package forum10699038;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;

import org.eclipse.persistence.jaxb.JAXBContextProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        // READ FROM XML
        JAXBContext jcXML = JAXBContext.newInstance(Metadata.class);

        File xml = new File("src/forum10699038/input.xml");
        Unmarshaller unmarshaller = jcXML.createUnmarshaller();
        Metadata metadata = (Metadata) unmarshaller.unmarshal(xml);

        // WRITE TO JSON
        Map<String, Object> properties = new HashMap<String, Object>(3);
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum10699038/oxm.xml");
        properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
        properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
        JAXBContext jcJSON = JAXBContext.newInstance(new Class[] {Metadata.class}, properties);

        Marshaller marshaller = jcJSON.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(metadata, System.out);
    }

}

输出

{
   "artist" : [ {
      "id" : "4302e264-1cf0-4d1f-aca7-2a6f89e34b36",
      "type" : "Group",
      "score" : "100",
      "name" : "Farming Incident",
      "ipi" : [ "1001" ]
   } ]
}

MOXy 和泽西岛

您可以在 JAXB-RS 环境(例如 Jersey)中轻松使用 MOXy 作为 JSON 提供程序:


其他文件

以下是我创建的文件版本,以确保一切正常。

输入.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#" xmlns:ext="http://musicbrainz.org/ns/ext#-2.0">
    <artist-list offset="0" count="1">
        <artist ext:score="100" type="Group"
            id="4302e264-1cf0-4d1f-aca7-2a6f89e34b36">
            <name>Farming Incident</name>
            <ipi-list>
                <ipi>1001</ipi>
            </ipi-list>
        </artist>
    </artist-list>
</metadata>

元数据

package forum10699038;

import javax.xml.bind.annotation.*;

@XmlRootElement
public class Metadata {

    @XmlElement(name="artist-list")
    ArtistList artistList;

}

艺术家名单

package forum10699038;

import java.util.List;

public class ArtistList {

    private List<Artist> artist;

}

艺术家

package forum10699038;

import javax.xml.bind.annotation.*;

@XmlType(propOrder={"name", "ipiList"})
public class Artist {

    @XmlAttribute
    private String id;

    @XmlAttribute
    private String type;

    @XmlAttribute(namespace="http://musicbrainz.org/ns/ext#-2.0")
    private String score;

    @XmlElement(name="ipi-list")
    private IPIList ipiList;

    private String name;

}

IP列表

package forum10699038;

import java.util.List;

public class IPIList {

    private List<String> ipi;

}

包信息

@XmlSchema( 
    namespace = "http://musicbrainz.org/ns/mmd-2.0#", 
    elementFormDefault = XmlNsForm.QUALIFIED,
    xmlns={
        @XmlNs(prefix="", namespaceURI = "http://musicbrainz.org/ns/mmd-2.0#")
    }
) 
@XmlAccessorType(XmlAccessType.FIELD)
package forum10699038;

import javax.xml.bind.annotation.*;
于 2012-06-13T09:47:38.570 回答
1

Jersey 创建的 JSON 是网站上提供的该模型的精确 JSOON 表示。您在这里面临的问题是该站点提供了一个笨拙的数据模型,而不是该框架没有做正确的事情。

为什么此服务返回艺术家列表类型的对象而不是返回艺术家列表?为什么服务也有一个 ipi-list 对象?您应该问的真正问题应该是,应该如何对其建模以更好地与所有技术一起使用。

于 2012-06-09T20:15:48.600 回答
1

我个人不太喜欢注释。有用纯代码生成 JSON/XML 的习惯。:)

例如杰克逊(Gson 也类似):

mapper = new ObjectMapper();
JsonNode root = mapper.createObjectNode();

JsonNode artist = mapper.createObjectNode();
artist.put("score", "100");
root.put("artist-list", artist);

ArrayNode ipiList = mapper.createArrayNode();
ipi.add("1001");
artist.put("ipi-list", ipiList);

表面上看起来可能需要做很多工作。但对我来说,这是将 JSON 映射到对象的非常清晰的方法。基本上在实体类中拥有 toJson() 方法是我的惯常做法。这是一个示例:https ://github.com/richardzcode/metrics/blob/master/src/main/java/com/rz/metrics/core/entities

虽然只是我。

对于 JAXB,我相信您需要如下注释您的实体:

@XmlElement(name = "ipi-list")
private List<Ipi> ipi;
于 2012-06-11T21:50:50.710 回答
1

我认为您在 ipiList 中看到的问题是由于 Jersey 用于映射到 JSON 的底层库中的单元素数组/列表存在问题。

以下博客文章(不是我的)显示了配置 Jersey 的一种方法,并且评论链接到替代(可能更简单)的方法,以使 JSON 表示对数组正确:

http://tugdualgrall.blogspot.co.uk/2011/09/jax-rs-jersey-and-single-element-arrays.html

于 2012-06-11T22:10:37.077 回答
0

我设法解决了 Jersey json 库中的 JSON 数组和原始字段“bug”。秘密成分是前面提到的 JSONConfiguration 和 ContextResolver 魔术。请参阅我的以下帖子,它有一个完整的代码示例,自定义的 ContextResolver 和 rest Application 类乍一看可能有点模糊逻辑。

如何使用 Jersey REST 序列化 Java 原语

  • 用于零或单元素 Java 列表的 json 数组
  • 没有引号字符的原始整数或布尔字段
于 2012-09-27T16:14:54.550 回答