如何从 Java 中的 JSON 对象中删除所有 JSON 格式(不仅仅是空格)?
How to remove all JSON formatting (not just whitespace) from a JSON object in Java?
我有一个这样的 JSON 对象:
{
"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"
}
}
我想从中删除所有 JSON 格式(空格、逗号、括号、方括号、引号、冒号)并生成如下输出:
shippingLinescarrierNZPostpriceamount5.50currencyNZDtaxAmountamount5.325currencyNZDreferenceINV000045totalAmountamount35.5currencyNZDreturnUrlssuccessUrlhttp://yourserver.com/successfailUrlhttp://.yourserver.com/failcallbackUrlhttp://yourserver.com/fail-safe-callback
所以我尝试了一堆 replaceAll()
如下所示:
String json = objectMapper.writeValueAsString(<Json Class here>); // using Jackson
json.replaceAll("\"", "")
.replaceAll("\{","")
.replaceAll("\}","")
.replaceAll("\[","")
.replaceAll("\]","")
.replaceAll(":","")
.replaceAll(",","")
.replaceAll(" ","");
但这也替换了 URL 中的 "colon" (http://...) 在 returnUrls
对象中。
有没有更好的方法来实现这一目标?
注意:我在Java 7.
要删除键后的冒号首先只删除
":
完成后得到新字符串。现在删除
"
分三步就可以了,不知道你有没有其他情况。
第 1 步:将所有 http://
替换为某物。例如,http:__
第 2 步:您当前的。
第 3 步:与第 1 步相反。
如果问题完全是 http://
,那么您可以将 http//
替换为原来的 http://
。
String output1= json.replaceAll("\"", "")
.replaceAll("\{","")
.replaceAll("\}","")
.replaceAll("\[","")
.replaceAll("\]","")
.replaceAll(":","")
.replaceAll(",","")
.replaceAll(" ","")
.replaceAll("\\","")
.replaceAll("http//", "http://");
不过要小心,因为如果您的 json 曾经包含您不想替换的 http//
,这将导致不需要的替换。
一个字符一个字符地查找。按原样复制引号之间的内容
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;
}
}
在附加到字符串、StringBuilder 等方面进行了优化...但以上是它的基本要点。
正如其他人所指出的,这不处理字符串中转义序列的情况:
"A string with an \"escaped\" quote include \u1234 and \b or \t"
我将把它留给你作为练习。
您可以使用正则表达式。这对你有帮助。
正则表达式 [^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-./]", "");
}
}
我们可以先转成yaml,这样替换起来会更简单更通用。 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 依赖项:
<!-- 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>
输出:
shippingLinescarrierNZPostpriceamount5.5currencyNZDtaxAmountamount5.325currencyNZDreferenceINV000045totalAmountamount35.5currencyNZDreturnUrlssuccessUrlhttp//yourserver/successfailUrlhttp//yourserver/failcallbackUrlhttp//yourserver/failsafecallback
这是另一种方法。这个想法是遍历所有元素,return它们的字符串表示,删除空格。
// 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");
}
顺便说一句,如果你想去掉所有看起来不像节点值的东西(例如,你希望 "NZ Post" 变成 "NZPost"),你为什么首先将它解析为 JSON?
我有一个这样的 JSON 对象:
{
"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"
}
}
我想从中删除所有 JSON 格式(空格、逗号、括号、方括号、引号、冒号)并生成如下输出:
shippingLinescarrierNZPostpriceamount5.50currencyNZDtaxAmountamount5.325currencyNZDreferenceINV000045totalAmountamount35.5currencyNZDreturnUrlssuccessUrlhttp://yourserver.com/successfailUrlhttp://.yourserver.com/failcallbackUrlhttp://yourserver.com/fail-safe-callback
所以我尝试了一堆 replaceAll()
如下所示:
String json = objectMapper.writeValueAsString(<Json Class here>); // using Jackson
json.replaceAll("\"", "")
.replaceAll("\{","")
.replaceAll("\}","")
.replaceAll("\[","")
.replaceAll("\]","")
.replaceAll(":","")
.replaceAll(",","")
.replaceAll(" ","");
但这也替换了 URL 中的 "colon" (http://...) 在 returnUrls
对象中。
有没有更好的方法来实现这一目标?
注意:我在Java 7.
要删除键后的冒号首先只删除
":
完成后得到新字符串。现在删除
"
分三步就可以了,不知道你有没有其他情况。
第 1 步:将所有 http://
替换为某物。例如,http:__
第 2 步:您当前的。
第 3 步:与第 1 步相反。
如果问题完全是 http://
,那么您可以将 http//
替换为原来的 http://
。
String output1= json.replaceAll("\"", "")
.replaceAll("\{","")
.replaceAll("\}","")
.replaceAll("\[","")
.replaceAll("\]","")
.replaceAll(":","")
.replaceAll(",","")
.replaceAll(" ","")
.replaceAll("\\","")
.replaceAll("http//", "http://");
不过要小心,因为如果您的 json 曾经包含您不想替换的 http//
,这将导致不需要的替换。
一个字符一个字符地查找。按原样复制引号之间的内容
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;
}
}
在附加到字符串、StringBuilder 等方面进行了优化...但以上是它的基本要点。
正如其他人所指出的,这不处理字符串中转义序列的情况:
"A string with an \"escaped\" quote include \u1234 and \b or \t"
我将把它留给你作为练习。
您可以使用正则表达式。这对你有帮助。
正则表达式 [^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-./]", "");
}
}
我们可以先转成yaml,这样替换起来会更简单更通用。 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 依赖项:
<!-- 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>
输出:
shippingLinescarrierNZPostpriceamount5.5currencyNZDtaxAmountamount5.325currencyNZDreferenceINV000045totalAmountamount35.5currencyNZDreturnUrlssuccessUrlhttp//yourserver/successfailUrlhttp//yourserver/failcallbackUrlhttp//yourserver/failsafecallback
这是另一种方法。这个想法是遍历所有元素,return它们的字符串表示,删除空格。
// 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");
}
顺便说一句,如果你想去掉所有看起来不像节点值的东西(例如,你希望 "NZ Post" 变成 "NZPost"),你为什么首先将它解析为 JSON?