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

make sure locale independent data is not upper/lowercased incorrectly… #317

Merged
merged 1 commit into from
Feb 20, 2017

Conversation

johnjaylward
Copy link
Contributor

…. See #315

@johnjaylward
Copy link
Contributor Author

Just for reference, Locale.ROOT was added in java6, which is why it was not in the original implementation. So this meets our current build requirement of JDK6.

@stleary
Copy link
Owner

stleary commented Feb 10, 2017

Sounds reasonable. I thought there was a Character.toLowerCase() in XMLTokener, is that not an issue? Unit tests will be needed as well.

@johnjaylward
Copy link
Contributor Author

I didn't see a locale option for the Character.toLowerCase() calls. Only for String.

@johnjaylward
Copy link
Contributor Author

johnjaylward commented Feb 10, 2017

@stleary maybe in the XML tokener instead of calling toLowerCase for each character, we call it with the toString on https://github.com/stleary/JSON-java/blob/master/XMLTokener.java#L139

like this:

    public Object nextEntity(char ampersand) throws JSONException {
        StringBuilder sb = new StringBuilder();
        for (;;) {
            char c = next();
            if (Character.isLetterOrDigit(c) || c == '#') {
                sb.append(c);
            } else if (c == ';') {
                break;
            } else {
                throw syntaxError("Missing ';' in XML entity: &" + sb);
            }
        }
        String string = sb.toString().toLowerCase(Locale.ROOT);
        Object object = entity.get(string);
        return object != null ? object : ampersand + string + ";";
}

@johnjaylward
Copy link
Contributor Author

johnjaylward commented Feb 10, 2017

Actually, for the nextEntity call, the locale should probably set to Locale.EN since all entities are either numeric or latin1 encoded.

  • < = &lt; or &#0060;

@stleary
Copy link
Owner

stleary commented Feb 10, 2017

I can add unit tests tonight, unless you will be making further changes to the code.

@johnjaylward
Copy link
Contributor Author

I won't make any more changes unless you think we need to modify the XMLTokenizer code. Thanks for taking care of the tests.

@stleary
Copy link
Owner

stleary commented Feb 11, 2017

Glad we have unit tests! Looks like JSONPointer needs more work, but not yet sure where.

public class MyLocaleBean {
    private final String üx = "Tlocaleüx";
    public String getÜx() {  return üx;    }
}

MyLocaleBean myLocaleBean = new MyLocaleBean();
JSONObject jsonObject = new JSONObject(myLocaleBean);
String str1 = (String)jsonObject.get("üx");
String str2 = (String)jsonObject.query("/getÜx");
System.out.println("str1: " + str1 + " str2: " + str2);

str1: Tlocale?x
str2: null

@stleary
Copy link
Owner

stleary commented Feb 11, 2017

On second thought:

String str1 = (String)jsonObject.get("üx");
String str2 = (String)jsonObject.query("/üx");

str1: Tlocale?x str2: Tlocale?x

@johnjaylward
Copy link
Contributor Author

johnjaylward commented Feb 11, 2017 via email

@stleary
Copy link
Owner

stleary commented Feb 11, 2017

Turned out I was just using the wrong query string, fixed now. But this code has to be saved as UTF, so I am putting the tests into a different file. Don't want someone saving JSONObjectTest as ASCII and having the tests fail.

@stleary
Copy link
Owner

stleary commented Feb 11, 2017

The following tests are successful without using the code in this pull request.

public class MyLocaleBean {
    private final String üx = "Tlocaleüx";
    private final String ü = "Tlocaleü";
    public String getÜx() {        return üx;    }
    public String getÜ() {        return ü;    }
}
        assertTrue("expected Tlocaleüx",
                "Tlocaleüx".equals(jsonObject.getString("üx")));
        assertTrue("expected Tlocalü",
                "Tlocaleü".equals(jsonObject.getString("ü")));
        assertTrue("expected Tlocaleüx",
                "Tlocaleüx".equals((String)(jsonObject.query("/üx"))));
        assertTrue("expected Tlocalü",
                "Tlocaleü".equals((String)(jsonObject.query("/ü"))));

To run the test I had to add this to build.gradle:

tasks.withType(JavaCompile) {
     // this subproject requires -parameters option
     options.compilerArgs << '-parameters'
     options.encoding = 'UTF-8'
}

My compiler version is: 1.8.0_05

Any suggestions?

@johnjaylward
Copy link
Contributor Author

johnjaylward commented Feb 12, 2017 via email

@stleary
Copy link
Owner

stleary commented Feb 17, 2017

What problem does this code solve?
JSONObject keys obtained from parsing beans should be invariant regardless of locale. This change enforces Locale.ROOT rules for lowercasing of the first letter of the key in get...() or is...() methods.

Risks
Low risk. This is likely a one-off that most developers are unlikely to see.

Changes to the API?
The first char of the key name is lowercased in a locale-invariant way when parsing beans.

Will this require a new release?
This change can be rolled into the next release.

Should the documentation be updated?
Not necessary at this time.

Does it break the unit tests?
No, but a unit test was added that will cause breakage until this change is committed. See stleary/JSON-Java-unit-test#64

Was any code refactored in this commit?
No, just the requested change was made.

Review status
ACCEPT. Starting 3 day comment window with this post.

@stleary stleary merged commit 724fb88 into stleary:master Feb 20, 2017
@johnjaylward johnjaylward deleted the fixLocale branch July 7, 2017 16:35
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

Successfully merging this pull request may close these issues.

2 participants