JAXB / Jackson 处理数组

发布于 2024-12-09 12:23:32 字数 2419 浏览 1 评论 0原文

我目前正在为 Web 应用程序编写 Jersey REST 接口。我想要的是能够将 JSON 和 XML 请求序列化到同一对象,但是我无法让 Jersey(即 JAXB / Jackson)以我想要的格式使用 XML 和 JSON。

XML 结构如下所示:

<?xml version="1.0" encoding="UTF-8" ?>
<message>
  <buckets>
    <bucket>
      <channels>
         <channel>Test A</channel>
         <channel>Test B</channel>
      </channels>
      <text>This is sample text</text>
    </bucket>
    <bucket>
      <channels>
        ....
      </channels>
      <text>This is sample text</text>
    </bucket>
  </buckets>
  <userId>10</userId>
 </message>

类如下所示:

@XmlRootElement(name="message")
public class MultiMessageRS {

    public static class Bucket {
        private List<String> channels;
        private String text;

        public Bucket () {}

        @XmlElementWrapper(name="channels")
        @XmlElement(name="channel")
        public List<String> getChannels() {
            return channels;
        }

        public void setChannels(List<String> channels) {
            this.channels = channels;
        }
        public String getText() {
            return text;
        }
        public void setText(String text) {
            this.text = text;
        }
    }

    private List<Bucket> buckets;

    private long userId;

    public MultiMessageRS () {}

    @XmlElementWrapper(name="buckets")
    @XmlElement(name="bucket")
    public List<Bucket> getBuckets() {
        return buckets;
    }
    public void setBuckets(List<Bucket> buckets) {
        this.buckets = buckets;
    }

    public long getUserId() {
        return userId;
    }
    public void setUserId(long userId) {
        this.userId = userId;
    }
}

这对于 XML 来说效果很好,但是它无法以我想要的格式使用 JSON。也就是说,问题在于它没有获取通道数组。格式如下:

{
   "buckets":[
      {
         "bucket":{
            "channels":[
               "twitter",
               "mobile"
            ],
            "text":"This is sample text"
         },
         "bucket":{
            "channels":[
               "email",
               "voice"
            ],
            "text":"This is sample text"
         }
      }
   ],
   "userId":"10"
}

为了能够正确地使用 JSON,我必须执行一些操作,例如在“channels”下添加一个“channel”数组,这是相当危险的。我该如何处理这种情况?

I'm currently writing a Jersey REST interface for a web application. What I want is the ability to be able to serialize a JSON and XML request to the same object however I'm having trouble getting the Jersey (i.e. JAXB / Jackson) to consume the XML and JSON in the format I want.

The XML structure looks like so:

<?xml version="1.0" encoding="UTF-8" ?>
<message>
  <buckets>
    <bucket>
      <channels>
         <channel>Test A</channel>
         <channel>Test B</channel>
      </channels>
      <text>This is sample text</text>
    </bucket>
    <bucket>
      <channels>
        ....
      </channels>
      <text>This is sample text</text>
    </bucket>
  </buckets>
  <userId>10</userId>
 </message>

The class looks like:

@XmlRootElement(name="message")
public class MultiMessageRS {

    public static class Bucket {
        private List<String> channels;
        private String text;

        public Bucket () {}

        @XmlElementWrapper(name="channels")
        @XmlElement(name="channel")
        public List<String> getChannels() {
            return channels;
        }

        public void setChannels(List<String> channels) {
            this.channels = channels;
        }
        public String getText() {
            return text;
        }
        public void setText(String text) {
            this.text = text;
        }
    }

    private List<Bucket> buckets;

    private long userId;

    public MultiMessageRS () {}

    @XmlElementWrapper(name="buckets")
    @XmlElement(name="bucket")
    public List<Bucket> getBuckets() {
        return buckets;
    }
    public void setBuckets(List<Bucket> buckets) {
        this.buckets = buckets;
    }

    public long getUserId() {
        return userId;
    }
    public void setUserId(long userId) {
        this.userId = userId;
    }
}

This works fine for the XML however it's unable to consume the JSON in the format I would like. Namely, the issue is that it isn't picking up the channels array. The format is as follows:

{
   "buckets":[
      {
         "bucket":{
            "channels":[
               "twitter",
               "mobile"
            ],
            "text":"This is sample text"
         },
         "bucket":{
            "channels":[
               "email",
               "voice"
            ],
            "text":"This is sample text"
         }
      }
   ],
   "userId":"10"
}

From it to work correctly with the JSON, I would have to do something like adding a 'channel' array under 'channels' which is pretty dodgy. How will I be able to handle this situation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

安静 2024-12-16 12:23:32

注意:我是EclipseLink JAXB (MOXy) 的领导者和 JAXB 2 的成员(JSR-222)专家组。

EclipseLink JAXB (MOXy) 提供对 JSON 绑定的本机支持。下面的示例演示了您在问题中发布的模型的 XML 和 JSON 表示形式。

演示

package forum7735245;

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

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(MultiMessageRS.class);

        File xml = new File("src/forum7735245/input.xml");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        MultiMessageRS message = (MultiMessageRS) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty("eclipselink.media-type", "application/json");
        marshaller.setProperty("eclipselink.json.include-root", false);
        marshaller.marshal(message, System.out);
    }

}

input.xml

<?xml version="1.0" encoding="UTF-8" ?>
<message>
  <buckets>
    <bucket>
      <channels>
         <channel>Test A</channel>
         <channel>Test B</channel>
      </channels>
      <text>This is sample text</text>
    </bucket>
    <bucket>
      <channels>
        ....
      </channels>
      <text>This is sample text</text>
    </bucket>
  </buckets>
  <userId>10</userId>
 </message>

输出

{
   "buckets" : {
      "bucket" : [ {
         "channels" : {
            "channel" : [ "Test A", "Test B" ]
         },
         "text" : "This is sample text"
      }, {
         "channels" :  {},
         "text" : "This is sample text"
      } ]
   },
   "userId" : 10
}

了解更多信息

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.

EclipseLink JAXB (MOXy) offers native support for JSON-binding. Below is an example demonstrating the XML and JSON representation of the model you posted in your question.

Demo

package forum7735245;

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

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(MultiMessageRS.class);

        File xml = new File("src/forum7735245/input.xml");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        MultiMessageRS message = (MultiMessageRS) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty("eclipselink.media-type", "application/json");
        marshaller.setProperty("eclipselink.json.include-root", false);
        marshaller.marshal(message, System.out);
    }

}

input.xml

<?xml version="1.0" encoding="UTF-8" ?>
<message>
  <buckets>
    <bucket>
      <channels>
         <channel>Test A</channel>
         <channel>Test B</channel>
      </channels>
      <text>This is sample text</text>
    </bucket>
    <bucket>
      <channels>
        ....
      </channels>
      <text>This is sample text</text>
    </bucket>
  </buckets>
  <userId>10</userId>
 </message>

Output

{
   "buckets" : {
      "bucket" : [ {
         "channels" : {
            "channel" : [ "Test A", "Test B" ]
         },
         "text" : "This is sample text"
      }, {
         "channels" :  {},
         "text" : "This is sample text"
      } ]
   },
   "userId" : 10
}

For More Information

堇年纸鸢 2024-12-16 12:23:32

我认为您的 JSON 过于复杂(并且通过重复相同的属性名称使其无效)。
看起来您可能想要使用的是这样的:

{
  "buckets":[
     {
        "channels":[
           "twitter",
           "mobile"
        ],
        "text":"This is sample text"
     }, {
        "channels":[
           "email",
           "voice"
        ],
        "text":"This is sample text"
     }
  ],
  "userId":"10"
}

应该按预期工作。

I think you are overcomplicating your JSON (as well as making it invalid by repeating same property name).
It seems like what you might want to use is something like:

{
  "buckets":[
     {
        "channels":[
           "twitter",
           "mobile"
        ],
        "text":"This is sample text"
     }, {
        "channels":[
           "email",
           "voice"
        ],
        "text":"This is sample text"
     }
  ],
  "userId":"10"
}

which should work as expected.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文