Skip to content

Deserialization of a date with @JsonFormat specified with locale that is not a language tag #3316

@MarkDavoren

Description

@MarkDavoren

At least a lack of clarity in the doc and possibly a lack of feature.

@jsonformat takes a locale string parameter. It is not stated, but it is required that locale be the language tag. Not anything more specific such as de-DE or de_DE.

Unfortunately, https://www.baeldung.com/jackson-jsonformat states you can.
@jsonformat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd@HH:mm:ss.SSSZ", locale = "en_GB")
though their example is for serialization and they don't actually show it working.

I don't know if there are countries using the same language that use different syntaxes for dates, but you don't support it.

The implementation of @jsonformat calls new Locale(localeStr) where the argument is the language. There are other constructors that allow specifying country. Note also according to the Locale doc, "For backward compatibility reasons, this constructor does not make any syntactic checks on the input."

If you specify de-DE or similar, the locale is not properly constructed and you end up using the default locale. Attempts to deserialize using such a bad locale fail if your default locale doesn't parse the date.

My default locale is en_US. Note that October is rendered as "Oct" in English and "Okt" in German.

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY )
@Getter
static class TestClass {
	@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MMM-dd", locale="de")
	java.util.Date datePLde;

	@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MMM-dd", locale="de_DE")
	java.util.Date datePLdeuDE;

	@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MMM-dd", locale="de-DE")
	java.util.Date datePLdedDE;
}

@Test
void test() throws JsonMappingException, JsonProcessingException {
	String json;
	TestClass jf;
	ObjectReader reader = new ObjectMapper().registerModule(new JavaTimeModule()).readerFor(TestClass.class);
	try {	// This passes correctly recognizing Okt
		json = "{\"datePLde\": \"2020-Okt-31\"}";
		jf = reader.readValue(json);
		log.info("datePL with de: " + jf.getDatePLde().toString());
	} catch (InvalidFormatException ex) {
		log.info("datePL with de: Invalid format exception " + ex.getMessage());
	}

	try {	// This throws an exception not recognizing Okt
		json = "{\"datePLdeuDE\": \"2020-Okt-31\"}";
		jf = reader.readValue(json);
		log.info("datePL with de_DE: " + jf.getDatePLdeuDE().toString());
	} catch (InvalidFormatException ex) {
		log.info("datePL with de_DE: Invalid format exception " + ex.getMessage());
	}

	try {	// This throws an exception not recognizing Okt
		json = "{\"datePLdedDE\": \"2020-Okt-31\"}";
		jf = reader.readValue(json);
		log.info("datePL with de-DE: " + jf.getDatePLdedDE().toString());
	} catch (InvalidFormatException ex) {
		log.info("datePL with de-DE: Invalid format exception " + ex.getMessage());
	}

	try {	// This passes recognizing Oct even though a German-like locale is (incorrectly) specified
		json = "{\"datePLdedDE\": \"2020-Oct-31\"}";
		jf = reader.readValue(json);
		log.info("datePL with Oct de-DE: " + jf.getDatePLdedDE().toString());
	} catch (InvalidFormatException ex) {
		log.info("datePL with Oct de-DE: Invalid format exception " + ex.getMessage());
	}

	Locale loc;
	loc = Locale.getDefault(); // Locale for default: 'English : United States'. Example: 2021-Oct-31
	log.info("Locale for default: '" + loc.getDisplayLanguage() + " : " + loc.getDisplayCountry() + "'. Example: " + new SimpleDateFormat("yyyy-LLL-dd", loc).format(jud));

	loc = new Locale("de"); // Locale for de: 'German : '. Example: 2021-Okt-31
	log.info("Locale for de: '" + loc.getDisplayLanguage() + " : " + loc.getDisplayCountry() + "'. Example: " + new SimpleDateFormat("yyyy-LLL-dd", loc).format(jud));

	loc = new Locale("de-DE"); // Locale for de-DE: 'de-de : '. Example: 2021-Oct-31 -- Using Default
	log.info("Locale for de-DE: '" + loc.getDisplayLanguage() + " : " + loc.getDisplayCountry() + "'. Example: " + new SimpleDateFormat("yyyy-LLL-dd", loc).format(jud));

	loc = new Locale("de_DE"); // Locale for de_DE: 'de_de : '. Example: 2021-Oct-31 -- Using Default
	log.info("Locale for de_DE: '" + loc.getDisplayLanguage() + " : " + loc.getDisplayCountry() + "'. Example: " + new SimpleDateFormat("yyyy-LLL-dd", loc).format(jud));
}

Metadata

Metadata

Assignees

Labels

3.2json-formatIssue/PR related to handling of `@JsonFormat` (or config equivalent)

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions