1 package com.fasterxml.jackson.failing; 2 3 import java.io.IOException; 4 import java.util.ArrayList; 5 import java.util.List; 6 import java.util.Objects; 7 8 import com.fasterxml.jackson.databind.*; 9 import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator; 10 11 // see [https://github.com/FasterXML/jackson-core/issues/384]: most likely 12 // can not be fixed, but could we improve error message to indicate issue 13 // with non-static type of `Car` and `Truck`, which prevent instantiation? 14 public class InnerClassNonStaticCore384Test extends BaseMapTest 15 { 16 static class Fleet { 17 private List<Vehicle> vehicles; 18 getVehicles()19 public List<Vehicle> getVehicles() { 20 return vehicles; 21 } 22 setVehicles(List<Vehicle> vehicles)23 public void setVehicles(List<Vehicle> vehicles) { 24 this.vehicles = vehicles; 25 } 26 27 @Override equals(Object o)28 public boolean equals(Object o) { 29 if (this == o) return true; 30 if (o == null || getClass() != o.getClass()) return false; 31 Fleet fleet = (Fleet) o; 32 return Objects.equals(vehicles, fleet.vehicles); 33 } 34 35 @Override hashCode()36 public int hashCode() { 37 return Objects.hash(vehicles); 38 } 39 } 40 41 static abstract class Vehicle { 42 private String make; 43 private String model; 44 Vehicle(String make, String model)45 protected Vehicle(String make, String model) { 46 this.make = make; 47 this.model = model; 48 } 49 Vehicle()50 public Vehicle() { 51 } 52 getMake()53 public String getMake() { 54 return make; 55 } 56 setMake(String make)57 public void setMake(String make) { 58 this.make = make; 59 } 60 getModel()61 public String getModel() { 62 return model; 63 } 64 setModel(String model)65 public void setModel(String model) { 66 this.model = model; 67 } 68 69 @Override equals(Object o)70 public boolean equals(Object o) { 71 if (this == o) return true; 72 if (!(o instanceof Vehicle)) return false; 73 Vehicle vehicle = (Vehicle) o; 74 return Objects.equals(make, vehicle.make) && 75 Objects.equals(model, vehicle.model); 76 } 77 78 @Override hashCode()79 public int hashCode() { 80 return Objects.hash(make, model); 81 } 82 } 83 84 class Car extends Vehicle { 85 private int seatingCapacity; 86 private double topSpeed; 87 Car(String make, String model, int seatingCapacity, double topSpeed)88 public Car(String make, String model, int seatingCapacity, double topSpeed) { 89 super(make, model); 90 this.seatingCapacity = seatingCapacity; 91 this.topSpeed = topSpeed; 92 } 93 Car()94 public Car() { 95 } 96 getSeatingCapacity()97 public int getSeatingCapacity() { 98 return seatingCapacity; 99 } 100 setSeatingCapacity(int seatingCapacity)101 public void setSeatingCapacity(int seatingCapacity) { 102 this.seatingCapacity = seatingCapacity; 103 } 104 getTopSpeed()105 public double getTopSpeed() { 106 return topSpeed; 107 } 108 setTopSpeed(double topSpeed)109 public void setTopSpeed(double topSpeed) { 110 this.topSpeed = topSpeed; 111 } 112 113 @Override equals(Object o)114 public boolean equals(Object o) { 115 if (this == o) return true; 116 if (o == null || getClass() != o.getClass()) return false; 117 if (!super.equals(o)) return false; 118 Car car = (Car) o; 119 return seatingCapacity == car.seatingCapacity && 120 Double.compare(car.topSpeed, topSpeed) == 0; 121 } 122 123 @Override hashCode()124 public int hashCode() { 125 return Objects.hash(super.hashCode(), seatingCapacity, topSpeed); 126 } 127 } 128 129 class Truck extends Vehicle { 130 private double payloadCapacity; 131 Truck(String make, String model, double payloadCapacity)132 public Truck(String make, String model, double payloadCapacity) { 133 super(make, model); 134 this.payloadCapacity = payloadCapacity; 135 } 136 Truck()137 public Truck() { 138 } 139 getPayloadCapacity()140 public double getPayloadCapacity() { 141 return payloadCapacity; 142 } 143 setPayloadCapacity(double payloadCapacity)144 public void setPayloadCapacity(double payloadCapacity) { 145 this.payloadCapacity = payloadCapacity; 146 } 147 148 @Override equals(Object o)149 public boolean equals(Object o) { 150 if (this == o) return true; 151 if (o == null || getClass() != o.getClass()) return false; 152 if (!super.equals(o)) return false; 153 Truck truck = (Truck) o; 154 return Double.compare(truck.payloadCapacity, payloadCapacity) == 0; 155 } 156 157 @Override hashCode()158 public int hashCode() { 159 return Objects.hash(super.hashCode(), payloadCapacity); 160 } 161 } 162 163 /* 164 /********************************************************************** 165 /* Test methods 166 /********************************************************************** 167 */ 168 testHierarchy()169 public void testHierarchy() throws IOException { 170 ObjectMapper mapper = jsonMapperBuilder() 171 .activateDefaultTyping(NoCheckSubTypeValidator.instance) 172 .build(); 173 174 Fleet fleet = initVehicle(); 175 176 /* 177 for (Vehicle v : fleet.vehicles) { 178 System.out.println("Vehicle, type: "+v.getClass()); 179 } 180 */ 181 String serializedFleet = mapper 182 .writerWithDefaultPrettyPrinter() 183 .writeValueAsString(fleet); 184 185 //System.out.println(serializedFleet); 186 187 Fleet deserializedFleet = mapper.readValue(serializedFleet, Fleet.class); 188 189 assertTrue(deserializedFleet.getVehicles().get(0) instanceof Car); 190 assertTrue(deserializedFleet.getVehicles().get(1) instanceof Truck); 191 192 assertEquals(fleet, deserializedFleet); 193 } 194 initVehicle()195 private Fleet initVehicle() { 196 Car car = new Car("Mercedes-Benz", "S500", 5, 250.0); 197 Truck truck = new Truck("Isuzu", "NQR", 7500.0); 198 199 List<Vehicle> vehicles = new ArrayList<>(); 200 vehicles.add(car); 201 vehicles.add(truck); 202 203 Fleet serializedFleet = new Fleet(); 204 serializedFleet.setVehicles(vehicles); 205 return serializedFleet; 206 } 207 } 208