AMARNATH NANDURI
AMARNATH NANDURI

Reputation: 21

JSON parser in Java automatically converting a String to a number/integer

I have a Java object that contains a few String variables. When creating a json message from a Java object if one of the String values is alpha numeric, then the conversion will return back a quoted value. Else the conversion will return back a numeric value.

Example:

Class User {
   String userid , password;
}

if userid = "tom" and password = "123456" then the JSON conversion returns back

"userid":"tom" and "password":123456 (numeric)

It should actually return "password":"123456"

How can I achieve this? I am using the Java parser from json.org and below is a snippet of code that converts the Java object to Json.

final JSONObject jsonObject = XML.toJSONObject(writer.toString());
res = jsonObject.toString(4);

Upvotes: 2

Views: 3464

Answers (2)

alexbt
alexbt

Reputation: 17085

You could use staxon library instead: its JsonXMLConfigBuilder lets you control the behavior during conversion (such as autoprimitive which lets you define how you want to handle primitive values). Here's the code:

String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root><userid>tom</userid><password>123456</password></root>";
ByteArrayOutputStream bao = new ByteArrayOutputStream();
JsonXMLConfig config = new JsonXMLConfigBuilder().autoArray(true).autoPrimitive(false).prettyPrint(true).build();
try {
    XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(IOUtils.toInputStream(xml));
    XMLEventWriter writer = new JsonXMLOutputFactory(config).createXMLEventWriter(bao);

    writer.add(reader);
    reader.close();
    writer.close();
} finally {
    bao.close();
}

String json = bao.toString();

JsonXMLConfigBuilder()...autoPrimitive(false) does the trick you are looking for: the number fields are kept as Strings.

With this code sample, you need to add Saxion + commons-io (just for IOUtils.toInputStream(xml)) :

<dependency>
    <groupId>de.odysseus.staxon</groupId>
    <artifactId>staxon</artifactId>
    <version>1.3</version>
</dependency>

<dependency>
   <groupId>commons-io</groupId>
   <artifactId>commons-io</artifactId>
   <version>2.4<version>
</dependency>

Some documentation on staxon:

Upvotes: 0

mariusz2108
mariusz2108

Reputation: 881

It's because of stringToValue method in JSONObject. It tries to guess a type. It's open source so you can change it if you want. Just return string.

/**
 * Try to convert a string into a number, boolean, or null. If the string
 * can't be converted, return the string.
 *
 * @param string
 *            A String.
 * @return A simple JSON value.
 */
public static Object stringToValue(String string) {
    if (string.equals("")) {
        return string;
    }
    if (string.equalsIgnoreCase("true")) {
        return Boolean.TRUE;
    }
    if (string.equalsIgnoreCase("false")) {
        return Boolean.FALSE;
    }
    if (string.equalsIgnoreCase("null")) {
        return JSONObject.NULL;
    }

    /*
     * If it might be a number, try converting it. If a number cannot be
     * produced, then the value will just be a string.
     */

    char initial = string.charAt(0);
    if ((initial >= '0' && initial <= '9') || initial == '-') {
        try {
            if (string.indexOf('.') > -1 || string.indexOf('e') > -1
                    || string.indexOf('E') > -1
                    || "-0".equals(string)) {
                Double d = Double.valueOf(string);
                if (!d.isInfinite() && !d.isNaN()) {
                    return d;
                }
            } else {
                Long myLong = new Long(string);
                if (string.equals(myLong.toString())) {
                    if (myLong.longValue() == myLong.intValue()) {
                        return Integer.valueOf(myLong.intValue());
                    }
                    return myLong;
                }
            }
        } catch (Exception ignore) {
        }
    }
    return string;
}

Upvotes: 1

Related Questions