XmlMapper: как сериализовать список в XML при управлении именем элемента - PullRequest
0 голосов
/ 13 марта 2019

Я пытаюсь выяснить, как сериализовать специализированный List в XML, используя XmlMapper (подкласс ObjectMapper), контролируя при этом имя внешней оболочки каждого элемента.

Желательно, чтобы я делал это с помощью аннотаций, а не путем настройки XmlMapper (к которому у меня, возможно, нет доступа).

Например, рассмотрим бизнес-объект, который расширяет ArrayList, например:

static class Photo {
    String name;
}

class Album extends ArrayList<Photo> {
}

Я хочу сериализовать эту модель для JSON и XML, например:

JSON:

[
  {
    "name": "..."
  },
  {
    "name": "..."
  }
]

XML:

<Album>
  <Photo>
    <Name>...</Name>
  </Photo>
  <Photo>
    <Name>...</Name>
  </Photo>
<Album>

Я очень близко подошел к тому, чтобы выяснить, как это сделать, и я успешно построил версии вышеупомянутой модели для поддержки любого формата, но я не могу заставить ни одну версию поддерживать оба формата одновременно.

В случае, если непонятно, о чем я спрашиваю, рассмотрите следующий прохождение модульного теста (который представляет собой упрощенное представление моей проблемы), а затем обратитесь к TODO:

public class SpecializedListTest {

    @JsonRootName("Photo")
    class Photo {

        @JsonProperty("name")
        String name;

    }

    @JsonRootName("Album")
    class Album1 extends ArrayList<Photo> {}

    Album1 getAlbum1() {
        Album1 album = new Album1();
        Photo photo = new Photo();
        photo.name = "Hawaii";
        album.add(photo);
        album.add(photo);
        return album;
    }

    @Test
    public void serializeAlbum1ToJson() throws JsonProcessingException {
        Album1 album = getAlbum1();
        ObjectMapper mapper = new ObjectMapper();
        String actual = mapper.writeValueAsString(album);
        String expected = "[{'name':'Hawaii'},{'name':'Hawaii'}]".replace('\'', '"');
        assertEquals(expected, actual);
    }

    @Test
    public void serializeAlbum1ToXml() throws JsonProcessingException {
        Album1 album = getAlbum1();
        ObjectMapper mapper = new XmlMapper();
        String actual = mapper.writeValueAsString(album);
        // TODO Render as "<Photo>" instead of "<item">.
        String expected = "<Album><item><name>Hawaii</name></item><item><name>Hawaii</name></item></Album>";
        assertEquals(expected, actual);
    }

    @JsonRootName("Album")
    class Album2 {

        @JsonProperty
        @JacksonXmlElementWrapper(useWrapping = false)
        @JacksonXmlProperty(localName = "Photo")
        private final List<Photo> photos = new ArrayList<>();

    }

    Album2 getAlbum2() {
        Album2 album = new Album2();
        Photo photo = new Photo();
        photo.name = "Hawaii";
        album.photos.add(photo);
        album.photos.add(photo);
        return album;
    }

    @Test
    public void serializeAlbum2ToJson() throws JsonProcessingException {
        Album2 album = getAlbum2();
        ObjectMapper mapper = new ObjectMapper();
        String actual = mapper.writeValueAsString(album);
        // TODO Render as list, not object: [{"name":"Hawaii"},{"name":"Hawaii"}]
        String expected = "{'photos':[{'name':'Hawaii'},{'name':'Hawaii'}]}".replace('\'', '"');
        assertEquals(expected, actual);
    }

    @Test
    public void serializeAlbum2ToXml() throws JsonProcessingException {
        Album2 album = getAlbum2();
        ObjectMapper mapper = new XmlMapper();
        String actual = mapper.writeValueAsString(album);
        String expected = "<Album><Photo><name>Hawaii</name></Photo><Photo><name>Hawaii</name></Photo></Album>";
        assertEquals(expected, actual);
    }

}

Проблема с моделью на основе списка (Album1) заключается в том, что я не могу контролировать имя внешнего XML-элемента Photo. По умолчанию <item>.

Проблема с моделью списка-контейнера (Album2) заключается в том, что список представлен в виде свойства объекта, и я хочу, чтобы выходные данные представляли собой массив JSON, а не объект.

Я не могу согласиться с различными форматами вывода, потому что я пишу совместимую замену для существующего устаревшего продукта. Я знаю, что, возможно, смогу решить эту проблему с помощью специального сериализатора, но я надеюсь избежать этого.

Есть идеи?

...