Reputation: 1118
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
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
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
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
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
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
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
Reputation: 704
To remove colon after key First remove only
":
After completion get new string. Now remove
"
Upvotes: -1