0

I'm having my first attempt at using JSON. I've got some code that serialises my objects just fine, but trying to deserialise I get a MismatchedInputException, Cannot deserialize instance of com.john.irrigator3.irrigation.WateringSchedule out of START_ARRAY token

I guess Jackson is having trouble deserialising an array in my WateringScheduleCollection and I've tried changing the names of the method for adding to the array, creating no argument constructors, but I'm stuck. Can someone tell me where I'm going wring please?

WaterScheduleCollection:

public class WateringScheduleCollection {

    Map<String, WateringSchedule> schedules = new LinkedHashMap<>();

    public void removeSchedule(String name) {
        schedules.remove(name);
    }

    public void addSchedule(WateringSchedule wateringSchedule) {
        schedules.put(wateringSchedule.getName(), wateringSchedule);
    }

    public Map<String, WateringSchedule> getSchedules() {
        return schedules;
    }
}

WateringSchedule:

public class WateringSchedule {
    String name;
    ArrayList<WateringRoutine> wateringRoutines;
    SeasonLimits seasonLimits = null;
    int sprinkleDuration = 30;

    public WateringSchedule() {
        wateringRoutines = new ArrayList<WateringRoutine>();
    }

    public WateringSchedule(List<WateringRoutine> wateringRoutines) {
        this();
        for (WateringRoutine wateringRoutine : wateringRoutines) {
            addWateringRoutine(wateringRoutine);
        }
    }

    public void addWateringRoutine(WateringRoutine wateringRoutine) {
        wateringRoutines.add(wateringRoutine);
    }

    public ArrayList<WateringRoutine> getWateringRoutines() {
        return wateringRoutines;
    }

Serialising works fine with this:

 public void writeFile(){
        WateringRoutine wr1 = new WateringRoutine(0,1,10);
        WateringRoutine wr2 = new WateringRoutine(1,2,100);
        WateringRoutine wr3 = new WateringRoutine(2,3,1000);
        SeasonLimits seasonLimits = new SeasonLimits(4, 1, 6, 7);

        WateringSchedule wateringSchedule1 = new WateringSchedule();
        wateringSchedule1.setName("wateringSchedule1");
        wateringSchedule1.addWateringRoutine(wr1);
        wateringSchedule1.addWateringRoutine(wr2);

        WateringSchedule wateringSchedule2 = new WateringSchedule();
        wateringSchedule2.setName("wateringSchedule2");
        wateringSchedule2.addWateringRoutine(wr2);
        wateringSchedule2.addWateringRoutine(wr3);

        WateringSchedule wateringSchedule3 = new WateringSchedule();
        wateringSchedule3.setName("wateringSchedule3");
        wateringSchedule3.addWateringRoutine(wr1);
        wateringSchedule3.addWateringRoutine(wr2);
        wateringSchedule3.addWateringRoutine(wr3);
        wateringSchedule3.setSeasonLimits(seasonLimits);

        WateringScheduleCollection wateringScheduleCollection = new WateringScheduleCollection();
        wateringScheduleCollection.addSchedule(wateringSchedule1);
        wateringScheduleCollection.addSchedule(wateringSchedule2);
        wateringScheduleCollection.addSchedule(wateringSchedule3);

        ObjectMapper mapper = new ObjectMapper();
        mapper.getSerializerProvider().setNullKeySerializer(new MyDtoNullKeySerializer());
        mapper.enable(SerializationFeature.INDENT_OUTPUT);

        String json = null;
        try {
            json = mapper.writeValueAsString(wateringScheduleCollection);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        System.out.println(json);
    }

giving this output:

{
  "schedules" : {
    "wateringSchedule1" : {
      "name" : "wateringSchedule1",
      "wateringRoutines" : [ {
        "secsWatering" : 1,
        "hoursAllowedWithoutWater" : 10.0,
        "scheduleSprinkle" : false,
        "age" : 0
      }, {
        "secsWatering" : 2,
        "hoursAllowedWithoutWater" : 100.0,
        "scheduleSprinkle" : false,
        "age" : 1
      } ],
      "seasonLimits" : null,
      "sprinkleDuration" : 30
    },
    "wateringSchedule2" : {
      "name" : "wateringSchedule2",
      "wateringRoutines" : [ {
        "secsWatering" : 2,
        "hoursAllowedWithoutWater" : 100.0,
        "scheduleSprinkle" : false,
        "age" : 1
      }, {
        "secsWatering" : 3,
        "hoursAllowedWithoutWater" : 1000.0,
        "scheduleSprinkle" : false,
        "age" : 2
      } ],
      "seasonLimits" : null,
      "sprinkleDuration" : 30
    },
    "wateringSchedule3" : {
      "name" : "wateringSchedule3",
      "wateringRoutines" : [ {
        "secsWatering" : 1,
        "hoursAllowedWithoutWater" : 10.0,
        "scheduleSprinkle" : false,
        "age" : 0
      }, {
        "secsWatering" : 2,
        "hoursAllowedWithoutWater" : 100.0,
        "scheduleSprinkle" : false,
        "age" : 1
      }, {
        "secsWatering" : 3,
        "hoursAllowedWithoutWater" : 1000.0,
        "scheduleSprinkle" : false,
        "age" : 2
      } ],
      "seasonLimits" : {
        "startOfSeason" : 1554098900367,
        "endOfSeason" : 1559887700367,
        "monthStart" : 4,
        "dayStart" : 1,
        "monthEnd" : 6,
        "dayEnd" : 7
      },
      "sprinkleDuration" : 30
    }
  }
}

but trying to deserialise with this code:

public void readFile() {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            WateringScheduleCollection wsc = objectMapper.readValue(new File(testPath+fileName), WateringScheduleCollection.class);
            System.out.println(wsc.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

results in:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.john.irrigator3.irrigation.WateringSchedule` out of START_ARRAY token
 at [Source: (File); line: 3, column: 15] (through reference chain: com.john.irrigator3.irrigation.WateringScheduleCollection["schedules"]->java.util.LinkedHashMap["schedule"])
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
pir8ped
  • 199
  • 1
  • 1
  • 8

2 Answers2

0

I think Jackson has problem with you choosing Collection implementations (LinkedHashMap, ArrayList), rather than interfaces (Map, List). Normally Jackson will pick some defaults (e.g. ArrayList for List I'm guessing).

Please refer to this Answer for specifying expected interface implementations:

Jackson - How to specify a single implementation for interface-referenced deserialization?

0

I've just found out what I was doing wrong. I was writing the JSON to a file, then reading the file to deserialise. Well that's what I thought I was doing. Turns out, I was writing one file and reading a different one. Having seen that stupid mistake, the JSON just worked, serialising and deser deserialising without a problem.

Thanks for your answer, but what I really need is a solution to stupidity.

pir8ped
  • 199
  • 1
  • 1
  • 8