Adhyatmik
Adhyatmik

Reputation: 1118

How to remove all JSON formatting (not just whitespace) from a JSON object in Java?

I have a JSON object like this:

{
    "shippingLines": [{
        "carrier": "NZ Post",
        "price": {
            "amount": 5.50,
            "currency": "NZD"
        }
    }],
    "taxAmount": {
        "amount": 5.325,
        "currency": "NZD"
    },
    "reference": "INV000045",
    "totalAmount": {
        "amount": 35.5,
        "currency": "NZD"
    },
    "returnUrls": {
        "successUrl": "http://yourserver/success",
        "failUrl": "http://yourserver/fail",
        "callbackUrl": "http://yourserver/fail-safe-callback"
    }
}

I want to strip off all JSON formatting (spaces, comma, parentheses, brackets, quotes, colon) from it and product an output like following:

shippingLinescarrierNZPostpriceamount5.50currencyNZDtaxAmountamount5.325currencyNZDreferenceINV000045totalAmountamount35.5currencyNZDreturnUrlssuccessUrlhttp://yourserver.com/successfailUrlhttp://.yourserver.com/failcallbackUrlhttp://yourserver.com/fail-safe-callback

so I tried a bunch of replaceAll() like below:

String json = objectMapper.writeValueAsString(<Json Class here>); // using Jackson
json.replaceAll("\"", "")
    .replaceAll("\\{","")
    .replaceAll("\\}","")
    .replaceAll("\\[","")
    .replaceAll("\\]","")
    .replaceAll(":","")
    .replaceAll(",","")
    .replaceAll(" ","");

But this also replaced the "colon" in the URL (http://...) in the returnUrls object. Is there a better way to achieve this ?

Note: I'm on Java 7.

Upvotes: 0

Views: 8641

Answers (7)

MC Emperor
MC Emperor

Reputation: 22997

Here's another approach. The idea is to traverse all elements, and return their string representation, with whitespace removed.

// Takes input and returns a string with all elements concatenated.
// withExactBigDecimals(true) makes sure trailing zeros (e.g. 5.50) will be
// preserved
static String toRawConcat(String input) throws IOException {
    ObjectMapper mapper = new ObjectMapper()
        .configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true)
        .configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true)
        .setNodeFactory(JsonNodeFactory.withExactBigDecimals(true));
    JsonNode node = mapper.readTree(input);
    return nodeToString(node);
}

// Removes whitespaces from a string
static String removeWs(String input) {
    return input.replaceAll("\\s+", "");
}

// Inspects the node type and returns the node contents as a string
private static String nodeToString(JsonNode node) {
    switch (node.getNodeType()) {
        case NULL:
        case BOOLEAN:
        case STRING:
            return removeWs(node.asText());
        case NUMBER:
            return node.decimalValue().toString();
        case ARRAY:
            {
                String s = "";
                Iterator<JsonNode> it = node.elements();
                while (it.hasNext()) {
                    s += nodeToString(it.next());
                }
                return s;
            }
        case OBJECT:
            {
                String s = "";
                Iterator<Entry<String, JsonNode>> it = node.fields();
                while (it.hasNext()) {
                    Entry<String, JsonNode> sub = it.next();
                    s += removeWs(sub.getKey()) + nodeToString(sub.getValue());
                }
                return s;
            }
        default:
            throw new UnsupportedOperationException("Node type " + node.getNodeType() + " not supported");
    }

By the way, if you want to strip just everything that doesn't look like a node value (e.g. you're expecting "NZ Post" to become "NZPost"), why are you parsing it as JSON in the first place?

Upvotes: 1

madhepurian
madhepurian

Reputation: 271

We can first convert it to yaml, then replacing would be more easier and generic. Like here

import java.io.IOException;

import org.springframework.util.StringUtils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;

public class Library {

    public static String asYaml(String jsonString) throws JsonProcessingException, IOException {
        // parse JSON
        JsonNode jsonNodeTree = new ObjectMapper().readTree(jsonString);
        // save it as YAML
        String jsonAsYaml = new YAMLMapper().writeValueAsString(jsonNodeTree);
        return jsonAsYaml;
    }
    public static void main(String[] args) {
        String jsonStr = "{\r\n" + 
                "    \"shippingLines\": [{\r\n" + 
                "        \"carrier\": \"NZ Post\",\r\n" + 
                "        \"price\": {\r\n" + 
                "            \"amount\": 5.50,\r\n" + 
                "            \"currency\": \"NZD\"\r\n" + 
                "        }\r\n" + 
                "    }],\r\n" + 
                "    \"taxAmount\": {\r\n" + 
                "        \"amount\": 5.325,\r\n" + 
                "        \"currency\": \"NZD\"\r\n" + 
                "    },\r\n" + 
                "    \"reference\": \"INV000045\",\r\n" + 
                "    \"totalAmount\": {\r\n" + 
                "        \"amount\": 35.5,\r\n" + 
                "        \"currency\": \"NZD\"\r\n" + 
                "    },\r\n" + 
                "    \"returnUrls\": {\r\n" + 
                "        \"successUrl\": \"http://yourserver/success\",\r\n" + 
                "        \"failUrl\": \"http://yourserver/fail\",\r\n" + 
                "        \"callbackUrl\": \"http://yourserver/fail-safe-callback\"\r\n" + 
                "    }\r\n" + 
                "}";
        try {
            String ymlstr = asYaml(jsonStr);
            System.out.println(ymlstr);
            ymlstr=StringUtils.replace(ymlstr, ":", "");
            ymlstr=StringUtils.replace(ymlstr, "-", "");
            ymlstr=StringUtils.replace(ymlstr, "\n", "");
            ymlstr=StringUtils.replace(ymlstr, " ", "");
            ymlstr=StringUtils.replace(ymlstr, "\"", "");
            System.out.println(ymlstr);
        } catch (JsonProcessingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
} 

Maven dependencies:

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.8.6</version>
</dependency>
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.8.6</version>
</dependency>
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml -->
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-yaml</artifactId>
    <version>2.8.6</version>
</dependency>

Output:

shippingLinescarrierNZPostpriceamount5.5currencyNZDtaxAmountamount5.325currencyNZDreferenceINV000045totalAmountamount35.5currencyNZDreturnUrlssuccessUrlhttp//yourserver/successfailUrlhttp//yourserver/failcallbackUrlhttp//yourserver/failsafecallback

Upvotes: 0

Pawan Maurya
Pawan Maurya

Reputation: 397

You can use regex for it. This will help you.

REGEX [^a-zA-Z0-9-./]

public class Test {

    public static void main(String[] args) {
        String jsonString = "{\n" +
                "    \"shippingLines\": [{\n" +
                "        \"carrier\": \"NZ Post\",\n" +
                "        \"price\": {\n" +
                "            \"amount\": 5.50,\n" +
                "            \"currency\": \"NZD\"\n" +
                "        }\n" +
                "    }],\n" +
                "    \"taxAmount\": {\n" +
                "        \"amount\": 5.325,\n" +
                "        \"currency\": \"NZD\"\n" +
                "    },\n" +
                "    \"reference\": \"INV000045\",\n" +
                "    \"totalAmount\": {\n" +
                "        \"amount\": 35.5,\n" +
                "        \"currency\": \"NZD\"\n" +
                "    },\n" +
                "    \"returnUrls\": {\n" +
                "        \"successUrl\": \"http://yourserver/success\",\n" +
                "        \"failUrl\": \"http://yourserver/fail\",\n" +
                "        \"callbackUrl\": \"http://yourserver/fail-safe-callback\"\n" +
                "    }\n" +
                "}";
        String format = jsonString.replaceAll("[^a-zA-Z0-9-./]", "");
    }
}

Upvotes: 0

Arpit Asati
Arpit Asati

Reputation: 140

If the issue is strictly the http://, then you could replace http// by the original http://.

   String output1=    json.replaceAll("\"", "")
                    .replaceAll("\\{","")
                    .replaceAll("\\}","")
                    .replaceAll("\\[","")
                    .replaceAll("\\]","")
                    .replaceAll(":","")
                    .replaceAll(",","")
                    .replaceAll(" ","")
                    .replaceAll("\\\\","")
                    .replaceAll("http//", "http://");

Careful though, as this will result in unwanted replacements if your json ever contains a http// that you don't wish to replace.

Upvotes: 0

selbie
selbie

Reputation: 104559

Go char by char. Copying stuff between quotes as is

String json = objectMapper.writeValueAsString(<Json Class here>); // using Jackson
String output = "";
int len = json.length();
boolean inQuotes = false;
for (int i = 0; i < len; i++)
{
    char c = json.charAt(i);
    if (c == '\"')
    {
        inQuotes = !inQuotes;
        continue;
    }
    if (inQuotes)
    {
        output = output + c;
    }
}

There's optimizations with regards to appending to strings, StringBuilder, etc... but the above is the basic gist of it.

As others have pointed out, this doesn't handle the case of an escape sequence within a string:

"A string with an \"escaped\" quote include \u1234 and \b or \t"

I'm going to leave that up you as an exercise.

Upvotes: 2

Tran Ho
Tran Ho

Reputation: 1500

You can do in three steps, not sure that you have any other case.

Step 1: Replace all http:// to something. For instance, http:__

Step 2: Your current one.

Step 3: Reverse it from step 1.

Upvotes: 0

Suman Kumar Dash
Suman Kumar Dash

Reputation: 704

To remove colon after key First remove only

":

After completion get new string. Now remove

"

Upvotes: -1

Related Questions