Java tutorial
/* * Copyright 2014 Bazaarvoice, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.bazaarvoice.jolt.jsonUtil.testdomain.five; import com.bazaarvoice.jolt.Diffy; import com.bazaarvoice.jolt.JsonUtil; import com.bazaarvoice.jolt.JsonUtils; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.node.ObjectNode; import org.testng.AssertJUnit; import org.testng.annotations.Test; import java.io.IOException; import java.util.Map; public class MappingTest5 { private Diffy diffy = new Diffy(); public static class QueryFilter5Deserializer extends JsonDeserializer<QueryFilter5> { /** * I tried moving this logic to be an @JsonDeserialize on the QueryFilter5 interface * but I could not get it to work. * * When this logic was moved there (and other logic was messed with), I would either get * A) Deserializaion error on the List<QueryFilter5> in the LogicalFilter5 or * B) stack overflow from bad recursion * * The problem with the List<QueryFilter5> in the LogicalFilter5, seemed like it * looked at the type of the first QueryFilter5, and assumed that all the elements in * the Array/List would be the same time, which totally breaks the goal of mixing * Real and Logical QueryFilter subclasses. */ @Override public QueryFilter5 deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { ObjectNode root = jp.readValueAsTree(); // pass in our objectCodec so that the subJsonParser knows about our configured Modules and Annotations JsonParser subJsonParser = root.traverse(jp.getCodec()); // Check if it is a "RealFilter" JsonNode valuesParam = root.get("values"); if (valuesParam == null) { return subJsonParser.readValueAs(LogicalFilter5.class); } if (!valuesParam.isArray()) { throw new RuntimeException("Expected an Array"); } return subJsonParser.readValueAs(RealFilter5.class); } } @Test public void testPolymorphicJacksonSerializationAndDeserialization() { ObjectMapper mapper = new ObjectMapper(); SimpleModule testModule = new SimpleModule("testModule", new Version(1, 0, 0, null, null, null)) .addDeserializer(QueryFilter5.class, new QueryFilter5Deserializer()); mapper.registerModule(testModule); // Verifying that we can pass in a custom Mapper and create a new JsonUtil JsonUtil jsonUtil = JsonUtils.customJsonUtil(mapper); String testFixture = "/jsonUtils/testdomain/five/queryFilter-realAndLogical5.json"; // TEST JsonUtil and our deserialization logic QueryFilter5 queryFilter = jsonUtil.classpathToType(testFixture, new TypeReference<QueryFilter5>() { }); // Make sure the hydrated QFilter looks right AssertJUnit.assertTrue(queryFilter instanceof LogicalFilter5); LogicalFilter5 andFilter = (LogicalFilter5) queryFilter; AssertJUnit.assertEquals(Operator.AND, andFilter.getOperator()); AssertJUnit.assertNotNull(andFilter.getValues()); AssertJUnit.assertEquals(3, andFilter.getValues().size()); // Make sure one of the top level RealFilters looks right QueryFilter5 productIdFilter = andFilter.getValues().get(1); AssertJUnit.assertTrue(productIdFilter instanceof StringRealFilter5); StringRealFilter5 stringRealProductIdFilter = (StringRealFilter5) productIdFilter; AssertJUnit.assertEquals(Field.PRODUCTID, stringRealProductIdFilter.getField()); AssertJUnit.assertEquals(Operator.EQ, stringRealProductIdFilter.getOperator()); AssertJUnit.assertEquals("Acme-1234", stringRealProductIdFilter.getValues().get(0)); // Make sure the nested OR looks right QueryFilter5 orFilter = andFilter.getValues().get(2); AssertJUnit.assertTrue(orFilter instanceof LogicalFilter5); LogicalFilter5 realOrFilter = (LogicalFilter5) orFilter; AssertJUnit.assertEquals(Operator.OR, realOrFilter.getOperator()); AssertJUnit.assertEquals(2, realOrFilter.getValues().size()); // Make sure nested AND looks right QueryFilter5 nestedAndFilter = realOrFilter.getValues().get(1); AssertJUnit.assertTrue(nestedAndFilter instanceof LogicalFilter5); AssertJUnit.assertEquals(Operator.AND, nestedAndFilter.getOperator()); AssertJUnit.assertEquals(3, nestedAndFilter.getValues().size()); // SERIALIZE TO STRING to test serialization logic String unitTestString = jsonUtil.toJsonString(queryFilter); // LOAD and Diffy the plain vanilla JSON versions of the documents Map<String, Object> actual = JsonUtils.jsonToMap(unitTestString); Map<String, Object> expected = JsonUtils.classpathToMap(testFixture); // Diffy the vanilla versions Diffy.Result result = diffy.diff(expected, actual); if (!result.isEmpty()) { AssertJUnit.fail("Failed.\nhere is a diff:\nexpected: " + JsonUtils.toJsonString(result.expected) + "\n actual: " + JsonUtils.toJsonString(result.actual)); } } }