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, "{}");
}
}