monkee
monkee

Reputation: 399

Using Jackson annotations to serialise objects to XML

I'm using Spring and Jackson to serialise objects before returning them as XML as part of an API. The Jackson documentation outlines that the root element name returned should match that of the object's class name.

I have the following model. I've explicitly set the root element to equal 'product'.

package example.models;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import javax.persistence.*;
import java.util.Date;

@Data
@Entity
@Table(name = "products")
@JacksonXmlRootElement(localName = "product")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @CreationTimestamp
    private Date createdAt;

    @UpdateTimestamp
    private Date updatedAt;
}

In my controller, I'm returning a response containing the list of products retrieved.

package example.controllers;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/api/products")
@RequiredArgsConstructor
public class ProductController {
    private final ProductRepository productRepository;

    @GetMapping(path = "/{id}", produces = {"application/json", "application/xml"})
    public ResponseEntity<Optional<Product>> getProduct(@PathVariable Long id) {
        return ResponseEntity.ok(this.productRepository.findById(id));
    }
}

When I hit the endpoint, /api/products/1 I get:

<Optional>
    <id>1</id>
    <name>Example</name>
    <createdAt>2019-12-18T12:44:12.536+0000</createdAt>
    <updatedAt>2019-12-18T12:44:12.536+0000</updatedAt>
</Optional>

Although, I'm expecting:

<product>
    <id>1</id>
    <name>Example</name>
    <createdAt>2019-12-18T12:44:12.536+0000</createdAt>
    <updatedAt>2019-12-18T12:44:12.536+0000</updatedAt>
</product>

How can I use Jackson/jackson-dataformat-xml to achieve this as it looks like my annotations have no effect?

Upvotes: 0

Views: 228

Answers (1)

ldz
ldz

Reputation: 2215

Change the endpoint to return a Product instead of Optional.

@GetMapping(path = "/{id}", produces = {"application/json", "application/xml"})
public ResponseEntity<Product> getProduct(@PathVariable Long id) {
    return ResponseEntity.ok(this.productRepository.findById(id).get());
}

Note: Optional.get() is used here for simplicity. The case of having no Product should be properly handled with Optional methods like isPresent() or orElse().

Upvotes: 1

Related Questions