有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java从JSON字符串中的任意位置移除键,而无需反序列化

在不反序列化和重新序列化以下深度嵌套的JSON字符串(如果可能的话)的情况下,如何从任何嵌套级别删除任何名为“REMOVEME”的键

尝试:

不情愿地尝试反序列化到JsonObject/LinkedHashMap以在有问题的键上使用node.remove(e.getKey())遍历结构,但Gson抛出并发修改异常,Jackson需要完全反序列化

之前:

{
    "a": {
        "REMOVEME" : "unwanted",
        "b": {
            "REMOVEME" : "unwanted",
            "c": {
                "d": {
                    "REMOVEME" : "unwanted",
                    "something": "default",
                    "e": {
                        "f": {
                            "REMOVEME" : "unwanted",
                            "g": {
                                "REMOVEME" : "unwanted",        
                                "h": {
                                    ... ,

之后:

{
    "a": {
        "b": {
            "c": {
                "d": {
                    "something": "default",
                    "e": {
                        "f": {
                            "g": {
                                "h": {
                                    ... ,

共 (3) 个答案

  1. # 1 楼答案

    我不确定您试图从节点删除属性的方式,但可以删除我使用jackson删除的属性

    String json = "{\n" + 
                "    \"a\": {\n" + 
                "        \"REMOVEME\" : \"unwanted\",\n" + 
                "        \"b\": {\n" + 
                "            \"REMOVEME\" : \"unwanted\"\n" + 
                "        }\n" + 
                "    }\n" + 
                "}";
    
        JsonNode node = objectMapper.readTree(json);
        ObjectNode node1 = (ObjectNode) node.get("a");
    
        node1.remove("REMOVEME");
        System.out.println(node1);  // {"b":{"REMOVEME":"unwanted"}}
        System.out.println(node);   // {"a":{"b":{"REMOVEME":"unwanted"}}}
    
  2. # 2 楼答案

    解决这个问题的一种方法是使用Gson进行流式令牌解析。这个方法可以轻松地处理非常大的JSON字符串

    前后示例:

    {"a":{"removeme":"unwanted","b":{"c":{"removeme":{"x":1},"d":{"e":123}}}}}
    {"a":{"b":{"c":{"d":{"e":123}}}}}
    

    基本测试线束:

    String rawJson = "{\"a\":{\"removeme\":\"unwanted\",\"b\":{\"c\":{\"removeme\":{\"x\":1},\"d\":{\"e\":123}}}}}";
    
    final Gson gson = new GsonBuilder().create();
    JsonReader reader = gson.newJsonReader( new StringReader( rawJson ) );
    
    StringWriter outWriter = new StringWriter();
    JsonWriter writer = gson.newJsonWriter( outWriter );
    
    JsonStreamFilter.streamFilter( reader, writer, Arrays.asList( "removeme" ) );
    
    System.out.println( rawJson );
    System.out.println( outWriter.toString() );
    

    标记化和过滤魔法:

    public class JsonStreamFilter
    {
        /**
         * Filter out all properties with names included in the `propertiesToRemove` list.
         * 
         * @param reader JsonReader to read in the JSON token
         * @param writer JsonWriter to accept modified JSON tokens
         * @param propertiesToRemove List of property names to remove
         * @throws IOException
         * @see Gson docs at https://sites.google.com/site/gson/streaming
         */
        public static void streamFilter(
            final JsonReader reader,
            final JsonWriter writer,
            final List<String> propertiesToRemove
        ) throws IOException
        {
            while ( true )
            {
                JsonToken token = reader.peek();
                switch ( token )
                {
                    case BEGIN_ARRAY:
                        reader.beginArray();
                        writer.beginArray();
                        break;
                    case END_ARRAY:
                        reader.endArray();
                        writer.endArray();
                        break;
                    case BEGIN_OBJECT:
                        reader.beginObject();
                        writer.beginObject();
                        break;
                    case END_OBJECT:
                        reader.endObject();
                        writer.endObject();
                        break;
                    case NAME:
                        String name = reader.nextName();
    
                        // Skip all nested structures stemming from this property
                        if ( propertiesToRemove.contains( name ) )
                        {
                            reader.skipValue();
                            break;
                        }
    
                        writer.name( name );
                        break;
                    case STRING:
                        String s = reader.nextString();
                        writer.value( s );
                        break;
                    case NUMBER:
                        String n = reader.nextString();
                        writer.value( new BigDecimal( n ) );
                        break;
                    case BOOLEAN:
                        boolean b = reader.nextBoolean();
                        writer.value( b );
                        break;
                    case NULL:
                        reader.nextNull();
                        writer.nullValue();
                        break;
                    case END_DOCUMENT:
                        return;
                }
            }
        }
    }
    
  3. # 3 楼答案

    如果对象的确切值和名称已知,则可以对其执行regex替换,而不使用任何内容,例如:

    jsonString.replaceAll("\"REMOVEME\" ?: ?\"unwanted\"[,}]","")
    

    否则,如果只知道键,仍然可以将其与稍微复杂的表达式匹配:

    \"REMOVEME\" ?: ?.+[,}]
    

    或者,如果只知道值,则返回

    \".+\" ?: ?\"unwanted\"[,}]
    

    如果它们都是动态的,但您仍然有一个列表,那么您应该能够遍历它们,动态地将每个键/值更改为匹配的键/值