Как удалить все форматирование JSON из объекта JSON в Java? - PullRequest
0 голосов
/ 20 сентября 2019

У меня есть объект 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 ( http: //.. .) В объекте returnUrls.Есть ли лучший способ добиться этого?

Примечание: я на Java 7 .

Ответы [ 7 ]

2 голосов
/ 20 сентября 2019

Перейти на символ за символом.Копирование содержимого между кавычками как есть

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 и т. Д., Но основа всего вышеизложенного.

Как указали другиеэто не относится к случаю escape-последовательности в строке:

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

Я оставлю это как упражнение.

1 голос
/ 20 сентября 2019

Вот другой подход.Идея состоит в том, чтобы обойти все элементы и вернуть их строковое представление с удаленными пробелами.

// 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?

0 голосов
/ 20 сентября 2019

Сначала мы можем преобразовать его в yaml, затем замена будет более простой и общей. Как здесь

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
0 голосов
/ 20 сентября 2019

Вы можете использовать регулярные выражения для него.Это поможет вам.

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-./]", "");
    }
}

0 голосов
/ 20 сентября 2019

Если проблема строго http://, то вы можете заменить http// на http://.

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

Осторожно, хотя , так как это приведет кнежелательные замены, если ваш json содержит http//, который вы не хотите заменять.

0 голосов
/ 20 сентября 2019

Вы можете сделать три шага, не будучи уверенным, что у вас есть какой-либо другой случай.

Шаг 1: Заменить все http:// на что-то.Например, http:__

Шаг 2: Ваш текущий.

Шаг 3: Отменить его с шага 1.

0 голосов
/ 20 сентября 2019

Чтобы удалить двоеточие после ключа Сначала удалите только

":

После завершения получите новую строку. Теперь удалите

"

...