2012-12-07 9 views
19

Muszę wykluczyć niektóre pola według nazw przed renderowaniem. Lista pól jest dynamiczna, więc nie mogę korzystać z adnotacji.Jak wykluczyć pola, w których Jackson nie używa adnotacji?

Próbowałem utworzyć niestandardowy serializer - ale nie mogę tam uzyskać nazwy pola.

W Gsonie użyłem ExclusionStrategy, ale Jackson nie ma takiej funkcjonalności. Czy to jest?

+0

Czy próbujesz wykluczyć właściwości w czasie wykonywania? Na przykład masz mapę i chcesz wykluczyć niektóre właściwości wewnątrz niej? – eugen

+0

tak, ale powinno to być wyjątek z notacją kropkową, taki jak 'order.id' ' order.content.items' – Roman

Odpowiedz

24

Poniższy przykład wykluczania pól według nazwy pochodzi z my blog post, Gson v Jackson - Part 4. (Wyszukaj PropertyFilterMixIn.) Ten przykład demonstruje użycie z podaną przez użytkownika listą nazw pól.

@JsonFilter("filter properties by name") 
class PropertyFilterMixIn {} 

class Bar 
{ 
    public String id = "42"; 
    public String name = "Fred"; 
    public String color = "blue"; 
    public Foo foo = new Foo(); 
} 

class Foo 
{ 
    public String id = "99"; 
    public String size = "big"; 
    public String height = "tall"; 
} 

public class JacksonFoo 
{ 
    public static void main(String[] args) throws Exception 
    { 
    ObjectMapper mapper = new ObjectMapper(); 
    mapper.getSerializationConfig().addMixInAnnotations( 
     Object.class, PropertyFilterMixIn.class); 

    String[] ignorableFieldNames = { "id", "color" }; 
    FilterProvider filters = new SimpleFilterProvider() 
     .addFilter("filter properties by name", 
      SimpleBeanPropertyFilter.serializeAllExcept( 
       ignorableFieldNames)); 
    ObjectWriter writer = mapper.writer(filters); 

    System.out.println(writer.writeValueAsString(new Bar())); 
    // output: 
    // {"name":"James","foo":{"size":"big","height":"tall"}} 
    } 
} 

(Uwaga:. Odpowiedni API mogą nieznacznie zmieniony w ostatnim wydaniu Jackson)

Chociaż przykład używa pozornie niepotrzebnych adnotacji adnotacji nie jest stosowana na polach mają być wyłączone. (Aby pomóc w zmianie interfejsu API, aby nieco uprościć niezbędną konfigurację, proszę nie wahaj się głosować na wydanie numeru JACKSON-274.

+1

Tak, to działa poprawnie. Dziękuję Ci. Ale nadal nie mogę tworzyć skomplikowanych wykluczeń, takich jak 'coś.itemów' (wyłączenie elementów z rootem czegoś) – Roman

+4

Szukam tej samej funkcji, której potrzebujesz, podanego rozwiązania, jeśli nie jest to wystarczające ani dla mojego przypadku, ponieważ użycie tego, co sugeruje, spowoduje wykluczenie pola o tej samej nazwie również w zagnieżdżonych obiektach. I chcę je wykluczyć tylko na najwyższym poziomie. Potrzebny jest więc sposób na określenie, na jakim poziomie właściwość musi być ignorowana. –

+1

Czy rozwiązanie jest teraz dostępne? – StackHola

6

Jackson korzysta z adnotacji dla większości takich rzeczy, ale nie musisz bezpośrednio opisywać wartość klasy. można również użyć „mix-in adnotacji” (patrz http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html).

i wtedy istnieje kilka opcji można użyć poza podstawowy @JsonIgnore (per-mienia) lub @JsonIgnoreProperties (per-klasy), patrz http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html

+1

Mówię o wykluczeniu w czasie wykonywania. Mam pytanie, jakie pola należy wykluczyć i które muszę wykluczyć z odpowiedzi – Roman

+1

Następnie najlepiej jest zbudować to sam, używając modelu drzewa; lub zaimplementuj "Filtr JSON" (z drugiego artykułu). Na szczęście @ {Programmer Bruce} pokazał, jak rozbrzmiewać. – StaxMan

+0

@JsonIgnore można również zastosować do metody getter. –

5

Jeśli masz filtry zdefiniowane na dwóch lub więcej pojo, możesz spróbować:

@JsonFilter("filterAClass") 
class AClass 
{  
    public String id = "42"; 
    public String name = "Fred"; 
    public String color = "blue"; 
    public int sal = 56; 
    public BClass bclass = new BClass(); 
} 

//@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 
@JsonFilter("filterBClass") 
class BClass 
{ 

    public String id = "99"; 
    public String size = "90"; 
    public String height = "tall"; 
    public String nulcheck =null; 
} 
public class MultipleFilterConcept { 
    public static void main(String[] args) throws Exception 
     { 
     ObjectMapper mapper = new ObjectMapper(); 
    // Exclude Null Fields 
     mapper.setSerializationInclusion(Inclusion.NON_NULL); 
     String[] ignorableFieldNames = { "id", "color" }; 
     String[] ignorableFieldNames1 = { "height","size" }; 
     FilterProvider filters = new SimpleFilterProvider() 
      .addFilter("filterAClass",SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames)) 
      .addFilter("filterBClass", SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames1)); 
     ObjectWriter writer = mapper.writer(filters); 
     System.out.println(writer.writeValueAsString(new AClass())); 

     } 
} 
9

Napisałem bibliotekę, aby poradzić sobie z podobnym przypadkiem użycia. Musiałem programowo ignorować pola w oparciu o dane żądające użytkownika. Normalne opcje Jacksona były zbyt ciężkie i nienawidziłem sposobu, w jaki wyglądał mój kod.

Biblioteka sprawia, że ​​o wiele łatwiej zrozumieć. Pozwala ona po prostu to zrobić:

import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.module.SimpleModule; 
import com.monitorjbl.json.JsonView; 
import com.monitorjbl.json.JsonViewSerializer; 
import static com.monitorjbl.json.Match.match; 

//initialize jackson 
ObjectMapper mapper = new ObjectMapper(); 
SimpleModule module = new SimpleModule(); 
module.addSerializer(JsonView.class, new JsonViewSerializer()); 
mapper.registerModule(module); 

//get a list of the objects 
List<MyObject> list = myObjectService.list(); 

String json; 
if(user.getRole().equals('ADMIN')){ 
    json = mapper.writeValueAsString(list); 
} else { 
    json = mapper.writeValueAsString(JsonView.with(list) 
     .onClass(MyObject.class, match() 
      .exclude("*") 
      .include("name"))); 
} 

System.out.println(json); 

Kod jest dostępny on GitHub, nadzieję, że to pomaga!

2

Napisałem bibliotekę o nazwie Squiggly Filter, która wybiera pola na podstawie podzbioru składni interfejsu Facebook Graph API. Na przykład, aby wybrać kod zip pola adresu obiektu użytkownika, należy użyć ciągu zapytania ?fields=address{zipCode}. Jedną z zalet Squiggly Filter jest to, że dopóki masz dostęp do ObjectMapper, który renderuje json, nie musisz modyfikować kodu żadnej z metod kontrolera.

Zakładając, że używasz API serwletów, można wykonać następujące czynności:

1) Zarejestruj filtr

<filter> 
    <filter-name>squigglyFilter</filter-name> 
    <filter-class>com.github.bohnman.squiggly.web.SquigglyRequestFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>squigglyFilter</filter-name> 
    <url-pattern>/**</url-pattern> 
</filter-mapping> 

2) zainicjować ObjectMapper

Squiggly.init(objectMapper, new RequestSquigglyContextProvider()); 

3) Ty może teraz filtrować twój json

curl https://yourhost/path/to/endpoint?fields=field1,field2{nested1,nested2} 

Więcej informacji na temat filtra Squiggly można znaleźć pod adresem github.

Powiązane problemy