Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow custom string representation of boolean values (e.g. "Y"/"N") #3310

Open
mjustin opened this issue Oct 25, 2021 · 4 comments
Open

Allow custom string representation of boolean values (e.g. "Y"/"N") #3310

mjustin opened this issue Oct 25, 2021 · 4 comments

Comments

@mjustin
Copy link

mjustin commented Oct 25, 2021

Is your feature request related to a problem? Please describe.
Sometimes it's necessary or desirable to represent a boolean value as a string (e.g. "Y"/"N"). For instance, an API not under your control may represent the value as such.

Describe the solution you'd like
An annotation-driven mechanism for specifying that a particular boolean or Boolean property maps to a particular true/false string values.

Usage example

{
  "awesome": "Y"
}
public class MaybeAwesome {
  // Some annotation(s) here to indicate "Y"/"N" should mapped to true/false
  private boolean awesome;

  // Getters & setters
}

Additional context
This was originally part of #1480, which got simplified to just handling 1/0.

#1480 (comment)

Ok: I think what I'll do is tackle serialization as 0/1 first, using @JsonFormat and Shape.NUMBER. This should be relatively easy to do.

Question of alternate String representations is more difficult, and a new issue should be filed for that.

I searched through open & closed issues since the creation of this ticket, and haven't found such an issue in the tracker.

@mjustin mjustin added the to-evaluate Issue that has been received but not yet evaluated label Oct 25, 2021
@GedMarc
Copy link

GedMarc commented Oct 25, 2021

Lots of problems with this, mainly being that Y/N is language, field and locale specific -

Here's something that you can do though -

public class BooleanModule extends SimpleModule
{
	public BooleanModule()
	{
		super("BooleanModule", Version.unknownVersion());
		addDeserializer(Boolean.class, new StringToBoolean())
				.addDeserializer(boolean.class, new JsonDeserializer()
				{
					@Override
					public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException
					{
						return new StringToBool().deserialize(p, ctxt);
					}
				})

I think there is also a direct reference to primitive boolean somewhere

public class StringToBoolean
		extends JsonDeserializer<Boolean>
{
	public static boolean nullable = true;

	@Override
	public Boolean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
	{
		return convert(p.getValueAsString());
	}

	public Boolean convert(String value)
	{
		if (Strings.isNullOrEmpty(value))
		{
			return null;
		}
		value = value.trim().toLowerCase();
		switch (value)
		{
			case "1":
			case "1.0":
			case "y":
			case "yes":
			case "on":
			case "true":
				return true;
			case "0":
			case "0.0":
			case "no":
			case "off":
			case "n":
			case "false":
				return false;
		}
		if(nullable)
			return null;
		else return false;
	}
}

@cowtowncoder cowtowncoder removed the to-evaluate Issue that has been received but not yet evaluated label Oct 26, 2021
@cowtowncoder
Copy link
Member

Hmmh. @JsonFormat does not really have anything, nor @JsonProperty; these would be common options for many other things.
But I wonder... perhaps from API perspective we could allow use of @JsonAlias for this use?

From that it would probably not be difficult to implement functionality suggested.

@mjustin
Copy link
Author

mjustin commented Oct 26, 2021

@GedMarc

Lots of problems with this, mainly being that Y/N is language, field and locale specific

I think it's field specific, but (at least the way I'm envisioning it), not locale specific per se. The cases I've seen this in the wild, there is one value for true, and a different one for false ("Y"/"N" being a specific case). I wouldn't want some sort of general purpose "guess what string means what", but rather to be able to explicitly and unambiguously state what the true value and false value is for a given Java property.

@mjustin
Copy link
Author

mjustin commented Oct 26, 2021

@cowtowncoder

But I wonder... perhaps from API perspective we could allow use of @JsonAlias for this use?

Unless I'm missing something, JsonAlias seems like an odd fit. It feels like JsonAlias is more about aliases for the name of the property, and not at all related to its value. It's also more about accepting additional noncanonical names for a property, and not for the primary/sole accepted value for it.

In this case, if I specified "Y"/"N", I probably wouldn't want to also allow true/false or "true"/"false".


Edit: I stand partially corrected. Apparently @JsonAlias can be used for values e.g. in an enum (per #2352); it's just not documented in the Javadocs. I've filed a bug report for this (FasterXML/jackson-annotations#193).

In that case… renaming a boolean really does feel like renaming an enum, so for consistency being able to configure it in a similar manner feels like it makes a lot of sense. However, with enums, I believe the @JsonAlias (or @JsonProperty/@JsonValue) has to be applied to the enum constant itself, and not to the field. It's not immediately clear to me if @JsonAlias could be used directly for this purpose without additions to the annotation since you certainly can't add it to e.g. Boolean.FALSE.

But that being said, @JsonAlias (or the like) makes sense for deserializing the value in addition to true/false. Something like @JsonProperty/@JsonValue is more what I'm looking for, which would allow for serializing and deserializing the value instead of true/false. It does feel like both would be useful things to implement, however.

@mjustin mjustin closed this as completed Oct 26, 2021
@mjustin mjustin reopened this Oct 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants