ical4j / ical4j-serializer

Marshalling iCalendar and vCard to XML and JSON formats
http://www.ical4j.org/serializer/
BSD 3-Clause "New" or "Revised" License
2 stars 2 forks source link

fails to marshal/unmarshal json #19

Open ChMThiel opened 6 months ago

ChMThiel commented 6 months ago

Following Test to marshal/unmarshal a calendar to/from json fails on reading it's own json

@Test
void shouldUnMarshalFromToJson() throws Exception {
        //given
        String cal = """
                     BEGIN:VCALENDAR
                     VERSION:2.0
                     PRODID:-// https://add-to-calendar-pro.com // button v2.5.10 //EN
                     CALSCALE:GREGORIAN
                     METHOD:PUBLISH
                     BEGIN:VTIMEZONE
                     TZID:Europe/Berlin
                     X-LIC-LOCATION:Europe/Berlin
                     LAST-MODIFIED:20240205T192834Z
                     BEGIN:DAYLIGHT
                     TZNAME:CEST
                     TZOFFSETFROM:+0100
                     TZOFFSETTO:+0200
                     DTSTART:19700329T020000
                     RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
                     END:DAYLIGHT
                     BEGIN:STANDARD
                     TZNAME:CET
                     TZOFFSETFROM:+0200
                     TZOFFSETTO:+0100
                     DTSTART:19701025T030000
                     RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
                     END:STANDARD
                     END:VTIMEZONE
                     BEGIN:VEVENT
                     UID:3c9de19f-1dec-4507-a41b-4213d270f359
                     DTSTAMP:20240220T065249Z
                     DTSTART;TZID=Europe/Berlin:20240209T140000
                     DTEND;TZID=Europe/Berlin:20240209T220000
                     SUMMARY:Day Shift
                     DESCRIPTION:Day shift
                     X-ALT-DESC;FMTTYPE=text/html:
                      <!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 3.2//EN"">
                      <HTML><BODY>
                      Late shift
                      </BODY></HTML>
                     RRULE:FREQ=WEEKLY;WKST=MO;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR
                     TRANSP:OPAQUE
                     SEQUENCE:0
                     STATUS:CONFIRMED
                     CREATED:20240220T065213Z
                     LAST-MODIFIED:20240220T065213Z
                     END:VEVENT
                     END:VCALENDAR
                     """;
        try (StringReader reader = new StringReader(cal);) {
            Calendar calendar = new CalendarBuilder().build(reader);
            assertFalse(calendar.validate().hasErrors());

            SimpleModule simpleModule = new SimpleModule();
            simpleModule.addSerializer(Calendar.class, new JCalSerializer(Calendar.class));
            simpleModule.addDeserializer(Calendar.class, new JCalMapper(Calendar.class));
            ObjectMapper mapper = new ObjectMapper();
            mapper.registerModule(simpleModule);
            //when write as json
            String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(calendar);
            //then
            System.out.println(json);
            //and read into Calendar agaon
            Calendar readValue = mapper.readValue(json, Calendar.class); //FAILS HERE
            //then
            System.out.println("read\n" + readValue);
        }
    }

reported exception: java.lang.ClassCastException: class net.fortuna.ical4j.model.component.Standard cannot be cast to class net.fortuna.ical4j.model.component.CalendarComponent (net.fortuna.ical4j.model.component.Standard and net.fortuna.ical4j.model.component.CalendarComponent are in unnamed module of loader 'app')

For me it seems, the JCalDecoder.DATE_TIME has a problem with decoding the TimeZone-Offset. @benfortuna any idea?

ChMThiel commented 6 months ago

After some research i found following: In JCalMapper.deserialze(...) row 57 there is a cast to CalendarComponent. But not all results of parseComponent(...) are CalendarComponents (see field componentFactoriesfor supported component-types. In my Case Standardis not a CalendarComponent which leads to to ClassCastException)

benfortuna commented 5 months ago

Thanks for the info. In fact, line 57 should only be parsing top-level components (e.g. VTIMEZONE, VEVENT, etc.) which are all sub-classes of CalendarComponent.

So there may be a problem with the parsing logic if it is returning a STANDARD component here. I will have a closer look.