JSON-java
JSON-java copied to clipboard
JSONObject.toString does not use an Enum's `toString()` but its `name()`
When calling the toString method of a JSONObject, if a field of the object is an enum, the name method is called (when constructing the string) instead of the toString method. This is problematic as name() is not overidable (as it is decalred final) whereas toString is.
I have found where this is in the sources.
Furthermore, it is specified in the java doc of the name function :
Most programmers should use the toString() method in preference to this one, as the toString method may return a more user-friendly name
The fix should be really easy, I can do it if it helps you. Is this an issue not tracked ? I have not found corresponding issues.
Here's a quick way to reproduce this default.
public class TestEnumToString {
enum MyEnum {
V_1, V_2;
@Override
public String toString() {
switch (this) {
case V_1:
return "1.0";
case V_2:
return "2.0";
};
return "";
}
}
public static void main(String[] args) throws JSONException {
JSONObject json = new JSONObject();
json.put("v1", MyEnum.V_1);
json.put("v2", MyEnum.V_2);
System.out.println(json.toString());
}
}
Thanks in advance, Arthur
Hi can I work on this?
@ThestralWarrior Sure, there are no restrictions on who gets to work on tickets. I don't know of anyone else working on this, so feel free to get started. Please keep in mind that changes to existing behavior are disallowed, unless there is a compelling reason for the change.
This is not a bug and was the intended way for enums to be serialized and deserialised by this library. This would be a major breaking change for anyone who is using the enum feature
I understand. It's my first time trying to make an open source contribution. I could use some guidance!
@ThestralWarrior No worries, this was an unusual issue since the obvious solution was not right for this project. There will be other opportunities to contribute.
This is not a bug and was the intended way for enums to be serialized and deserialised by this library. This would be a major breaking change for anyone who is using the enum feature
What is the workaround for this problem? JSONObject is treating Enum differently than any other class. If a user wants to serialize and deserialize an enum value using something other than name, there should be a way to do that. If it isn't by overriding toString() then what is it?
I see https://github.com/stleary/JSON-java/wiki/Tech:-How-to-solve-specific-problems-in-your-JSON-Java-code which talks about implementing JSONString. This appears to work one direction by implementing the toJSONString() function. What about the reverse? Is there an interface for fromJSONString()?
@robross0606 This is how the library was designed; there is no workaround. It may be possible for a future release to provide an option for alternative handling using a JSONParserConfiguration object and toString(), , but the support for that is not in place yet.
@stleary hi, i ran into this when upgrading from a 2002 (yes) version of the library.
You wrote:
This is how the library was designed
Just as a historical note, the code involved was introduced in 2016 in https://github.com/stleary/JSON-java/pull/271 - originally toString() was used (by default), and this was changed to name() for Enums.
Originally, .toString() was called on the enum element, which was overridable.
Yes, the original method of serialization for enums was broken as noted in the PR. As such we designed the bug fix around using the name of the enum.
This was mainly to ensure round tripping of bean -> json -> bean. Using the toString method would have made a round trip near impossible to do easily
The default behavior won't be changed. No objections if someone wants to add a JSONParserConfiguration option to get a different outcome.