2015-04-24 3 views
5

Я использую весну, чтобы создать успокоительный api, настолько хороший, мой вопрос заключается в том, как моделировать поля, которые идут в ответ динамически?Как динамически удалять поля из ответа json?

То контроллер, который я использую:

@Controller 

public class AlbumController { 

@Autowired 
private MusicService musicService; 

@RequestMapping(value = "/albums", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
@ResponseBody 
public Collection<Resource<Album>> getAllAlbums() { 

    Collection<Album> albums = musicService.getAllAlbums(); 
    List<Resource<Album>> resources = new ArrayList<Resource<Album>>(); 
    for (Album album : albums) { 
     resources.add(this.getAlbumResource(album)); 
    } 
    return resources; 

} 

@RequestMapping(value = "/album/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
@ResponseBody 
public Resource<Album> getAlbum(@PathVariable(value = "id") String id) { 

    Album album = musicService.getAlbum(id); 
    return getAlbumResource(album); 

} 

private Resource<Album> getAlbumResource(Album album) { 

    Resource<Album> resource = new Resource<Album>(album); 


    // Link to Album 
    resource.add(linkTo(methodOn(AlbumController.class).getAlbum(album.getId())).withSelfRel()); 
    // Link to Artist 
    resource.add(linkTo(methodOn(ArtistController.class).getArtist(album.getArtist().getId())).withRel("artist")); 
    // Option to purchase Album 
    if (album.getStockLevel() > 0) { 
     resource.add(linkTo(methodOn(AlbumController.class).purchaseAlbum(album.getId())).withRel("album.purchase")); 
    } 

    return resource; 

} 

@RequestMapping(value = "/album/purchase/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
@ResponseBody 
public Resource<Album> purchaseAlbum(@PathVariable(value = "id") String id) { 

    Album a = musicService.getAlbum(id); 
    a.setStockLevel(a.getStockLevel() - 1); 
    Resource<Album> resource = new Resource<Album>(a); 
    resource.add(linkTo(methodOn(AlbumController.class).getAlbum(id)).withSelfRel()); 
    return resource; 

} 
} 

И модель:

public class Album { 

private final String id; 
private final String title; 
private final Artist artist; 
private int stockLevel; 

public Album(final String id, final String title, final Artist artist, int stockLevel) { 
    this.id = id; 
    this.title = title; 
    this.artist = artist; 
    this.stockLevel = stockLevel; 
} 

public String getId() { 
    return id; 
} 

public String getTitle() { 
    return title; 
} 

public Artist getArtist() { 
    return artist; 
} 

public int getStockLevel() { 
    return stockLevel; 
} 

public void setStockLevel(int stockLevel) { 
    this.stockLevel = stockLevel; 
} 
} 
+0

Если ваш случай использования заключается в том, что в разных ответах вы хотите разные подмножества свойств, вы можете использовать [JSON views] (http://wiki.fasterxml.com/JacksonJsonViews) в jackson. – beerbajay

+0

Кажется, что я хочу, но если я буду использовать этот метод, мне придется управлять сортировкой вручную, поэтому, минуя весну, у вас есть пример этого? – danillosl

+0

В этом блоге (https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring) вы можете аннотировать ваши контроллеры с помощью '@JsonView (MyView.class) 'и spring применит представление для – beerbajay

ответ

3

я борюсь с этим требованием, тоже.

Следующий код обходной путь, используя JsonViews уже упоминаемый @beerbajay в комментарии к вашему вопросу:

http://wiki.fasterxml.com/JacksonJsonViews

Я использую Spring бутс 1.2.3.

Views.java

package demo; 

public class Views { 

    static interface Public {} 

    static interface Internal extends Public {} 
} 

Album.java

package demo; 

import com.fasterxml.jackson.annotation.JsonView; 

public class Album { 

    @JsonView(Views.Public.class) 
    private String id; 

    @JsonView(Views.Public.class) 
    private String title; 

    @JsonView(Views.Public.class) 
    private String artist; 

    @JsonView(Views.Internal.class) 
    private String secret; 

    public Album(String id, String title, String artist, String secret) { 
     this.id = id; 
     this.title = title; 
     this.artist = artist; 
     this.secret = secret; 
    } 

} 

AlbumController.java

package demo; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.http.MediaType; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.RestController; 

import com.fasterxml.jackson.core.JsonProcessingException; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.ObjectWriter; 

@RestController 
public class AlbumController { 

    @Autowired 
    ObjectMapper mapper; 

    @RequestMapping(value = "/album", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
    public String getAlbum() throws JsonProcessingException { 
     Album foo = new Album("1", "foo", "John Doe", "secretProperty"); 

     // replace the following value with runtime logic of your choice, 
     // e.g. role of a user 
     boolean forInternal = false; 

     ObjectWriter viewWriter; 
     if (forInternal) { 
      viewWriter = mapper.writerWithView(Views.Internal.class); 
     } else { 
      viewWriter = mapper.writerWithView(Views.Public.class); 
     } 

     return viewWriter.writeValueAsString(foo); 
    } 
} 

Таким образом, ключевым является использование Джэксон ObjectMapper и ObjectWriter сгенерировать строку представитель json иона вашего объекта.

Чувствует себя уродливым для меня, но работает. Конечно, остается вопрос, как это масштабируется при определении более одного RequestMapping.

+0

Кажется лучшим способом выбрать json шаблоны, спасибо за ответ, другой способ будет использовать описанные методы https://spring.io/blog/2014/12/02/latest-jackson -интегрирования-улучшения в пружине. – danillosl

+0

Я знаю, что это очень старый ответ, но вы также можете использовать @JsonIgnore в полях, которые вы хотите игнорировать из тела ответа. –

Смежные вопросы