001package io.ebean.test; 002 003import com.fasterxml.jackson.annotation.JsonInclude; 004import com.fasterxml.jackson.databind.DeserializationFeature; 005import com.fasterxml.jackson.databind.JsonNode; 006import com.fasterxml.jackson.databind.ObjectMapper; 007import com.fasterxml.jackson.databind.SerializationFeature; 008import com.fasterxml.jackson.databind.type.CollectionType; 009import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 010 011import java.io.IOException; 012import java.util.List; 013 014/** 015 * Helper to convert to and from json using Jackson object mapper and 016 * perform some useful asserts based on json content. 017 */ 018public class Json { 019 020 /** 021 * For reading resource json content into a bean, list or jsonNode in a fluid style. 022 */ 023 public static class Resource { 024 private final String resourcePath; 025 026 private Resource(String resourcePath) { 027 this.resourcePath = resourcePath; 028 } 029 030 /** 031 * Return as a plain bean. 032 */ 033 <T> T asBean(Class<T> cls) { 034 return Json.read(cls, readResource(resourcePath)); 035 } 036 037 /** 038 * Return as a list of beans. 039 */ 040 <T> List<T> asList(Class<T> cls) { 041 return Json.readList(cls, readResource(resourcePath)); 042 } 043 044 /** 045 * Return as a JsonNode. 046 */ 047 JsonNode asNode() { 048 return Json.readNodeFromResource(resourcePath); 049 } 050 } 051 052 private static final ObjectMapper MAPPER = initMapper(); 053 054 /** 055 * For fluid style reading resource json content and return as a 056 * bean, list of bean or JsonNode. 057 * <pre>{@code 058 * 059 * PlainBean bean = 060 * Json.resource("/example/plain-list.json").asBean(PlainBean.class); 061 * 062 * List<PlainBean> list = 063 * Json.resource("/example/plain-list.json").asList(PlainBean.class); 064 * 065 * JsonNode jsonNode = 066 * Json.resource("/example/plain-list.json").asJsonNode(); 067 * 068 * }</pre> 069 * 070 * @param resourcePath The resource path where the json content is read from 071 * @return The resource to convert to a bean or jsonNode etc 072 */ 073 public static Resource resource(String resourcePath) { 074 return new Resource(resourcePath); 075 } 076 077 /** 078 * Assert all the fields in the expectedJson are present in actualJson and values match. 079 */ 080 public static void assertContains(String actualJson, String expectedJson) { 081 assertContains(readNode(actualJson), readNode(expectedJson)); 082 } 083 084 /** 085 * Assert all the fields in the expectedJson are present in actualJson and values match. 086 */ 087 public static void assertContains(JsonNode actualJsonNode, JsonNode expectedJsonNode) { 088 JsonAssertContains.assertContains(actualJsonNode, expectedJsonNode); 089 } 090 091 /** 092 * Read the content for the given resource path. 093 */ 094 public static String readResource(String resourcePath) { 095 return IOUtils.readResource(resourcePath); 096 } 097 098 /** 099 * Return a bean from json content of a resource path. 100 */ 101 public static <T> T readFromResource(Class<T> type, String resourcePath) { 102 return read(type, readResource(resourcePath)); 103 } 104 105 /** 106 * Return a typed object from json content. 107 */ 108 public static <T> T read(Class<T> type, String json) { 109 try { 110 return MAPPER.readValue(json, type); 111 } catch (IOException e) { 112 throw new RuntimeException(e); 113 } 114 } 115 116 /** 117 * Return a list of a given type from json content. 118 */ 119 public static <T> List<T> readList(Class<T> type, String json) { 120 final CollectionType collectionType = MAPPER.getTypeFactory().constructCollectionType(List.class, type); 121 try { 122 return MAPPER.readValue(json, collectionType); 123 } catch (IOException e) { 124 throw new RuntimeException(e); 125 } 126 } 127 128 /** 129 * Parse json into a generic JsonNode structure from resource. 130 */ 131 public static JsonNode readNodeFromResource(String resourcePath) { 132 return readNode(IOUtils.readResource(resourcePath)); 133 } 134 135 /** 136 * Parse json into a generic JsonNode structure. 137 */ 138 public static JsonNode readNode(String json) { 139 try { 140 return MAPPER.readTree(json); 141 } catch (IOException e) { 142 throw new RuntimeException(e); 143 } 144 } 145 146 /** 147 * Serialize object to string 148 */ 149 public static String toJsonString(Object bean) { 150 try { 151 return MAPPER.writeValueAsString(bean); 152 } catch (IOException e) { 153 throw new RuntimeException(e); 154 } 155 } 156 157 private static ObjectMapper initMapper() { 158 return new ObjectMapper() 159 .registerModule(new JavaTimeModule()) 160 .configure(SerializationFeature.INDENT_OUTPUT, true) 161 .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) 162 .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) 163 .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) 164 .configure(SerializationFeature.INDENT_OUTPUT, true) 165 .setSerializationInclusion(JsonInclude.Include.NON_NULL); 166 } 167 168}