package com.fasterxml.jackson.databind.views; import java.io.*; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; /** * Unit tests for verifying JSON view functionality: ability to declaratively * suppress subset of properties from being serialized. */ public class TestViewSerialization extends BaseMapTest { // Classes that represent views static class ViewA { } static class ViewAA extends ViewA { } static class ViewB { } static class ViewBB extends ViewB { } static class Bean { @JsonView(ViewA.class) public String a = "1"; @JsonView({ViewAA.class, ViewB.class}) public String aa = "2"; @JsonView(ViewB.class) public String getB() { return "3"; } } /** * Bean with mix of explicitly annotated * properties, and implicit ones that may or may * not be included in views. */ static class MixedBean { @JsonView(ViewA.class) public String a = "1"; public String getB() { return "2"; } } /** * As indicated by [JACKSON-261], @JsonView should imply * that associated element (method, field) is to be considered * a property */ static class ImplicitBean { @JsonView(ViewA.class) private int a = 1; } static class VisibilityBean { @JsonProperty protected String id = "id"; @JsonView(ViewA.class) public String value = "x"; } public static class WebView { } public static class OtherView { } public static class Foo { @JsonView(WebView.class) public int getFoo() { return 3; } } /* /********************************************************** /* Unit tests /********************************************************** */ private final ObjectMapper MAPPER = objectMapper(); @SuppressWarnings("unchecked") public void testSimple() throws IOException { StringWriter sw = new StringWriter(); // Ok, first, using no view whatsoever; all 3 Bean bean = new Bean(); Map<String,Object> map = writeAndMap(MAPPER, bean); assertEquals(3, map.size()); // Then with "ViewA", just one property sw = new StringWriter(); MAPPER.writerWithView(ViewA.class).writeValue(sw, bean); map = MAPPER.readValue(sw.toString(), Map.class); assertEquals(1, map.size()); assertEquals("1", map.get("a")); // "ViewAA", 2 properties sw = new StringWriter(); MAPPER.writerWithView(ViewAA.class).writeValue(sw, bean); map = MAPPER.readValue(sw.toString(), Map.class); assertEquals(2, map.size()); assertEquals("1", map.get("a")); assertEquals("2", map.get("aa")); // "ViewB", 2 prop2 String json = MAPPER.writerWithView(ViewB.class).writeValueAsString(bean); map = MAPPER.readValue(json, Map.class); assertEquals(2, map.size()); assertEquals("2", map.get("aa")); assertEquals("3", map.get("b")); // and "ViewBB", 2 as well json = MAPPER.writerWithView(ViewBB.class).writeValueAsString(bean); map = MAPPER.readValue(json, Map.class); assertEquals(2, map.size()); assertEquals("2", map.get("aa")); assertEquals("3", map.get("b")); // and finally, without view. json = MAPPER.writerWithView(null).writeValueAsString(bean); map = MAPPER.readValue(json, Map.class); assertEquals(3, map.size()); } /** * Unit test to verify implementation of [JACKSON-232], to * allow "opt-in" handling for JSON Views: that is, that * default for properties is to exclude unless included in * a view. */ @SuppressWarnings("unchecked") public void testDefaultExclusion() throws IOException { MixedBean bean = new MixedBean(); // default setting: both fields will get included String json = MAPPER.writerWithView(ViewA.class).writeValueAsString(bean); Map<String,Object> map = MAPPER.readValue(json, Map.class); assertEquals(2, map.size()); assertEquals("1", map.get("a")); assertEquals("2", map.get("b")); // but can also change (but not necessarily on the fly...) ObjectMapper mapper = new ObjectMapper(); mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); // with this setting, only explicit inclusions count: json = mapper.writerWithView(ViewA.class).writeValueAsString(bean); map = mapper.readValue(json, Map.class); assertEquals(1, map.size()); assertEquals("1", map.get("a")); assertNull(map.get("b")); // but without view, view processing disabled: json = mapper.writer().withView(null).writeValueAsString(bean); map = mapper.readValue(json, Map.class); assertEquals(2, map.size()); assertEquals("1", map.get("a")); assertEquals("2", map.get("b")); } /** * As per [JACKSON-261], @JsonView annotation should imply that associated * method/field does indicate a property. */ public void testImplicitAutoDetection() throws Exception { assertEquals("{\"a\":1}", MAPPER.writeValueAsString(new ImplicitBean())); } public void testVisibility() throws Exception { VisibilityBean bean = new VisibilityBean(); // Without view setting, should only see "id" String json = MAPPER.writerWithView(Object.class).writeValueAsString(bean); //json = mapper.writeValueAsString(bean); assertEquals("{\"id\":\"id\"}", json); } // [JACKSON-868] public void test868() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); String json = mapper.writerWithView(OtherView.class).writeValueAsString(new Foo()); assertEquals(json, "{}"); } }