1

I am reading data in from a database, and then putting the data into a JSON object, which also contains an inner json object. Some of the data from the database comes back as "", and I want to remove the key and value for the object.

This is how the data comes:

 { 
  "foo": "bar",
   "bar": "",
   "foo": {
         "bar": "foo",
    },
    "bar": "foo"
    },

I want the data to look like this instead:

 { 
  "foo": "bar",
   "foo": {
         "bar": "foo",
    },
    "bar": "foo"
    },

I have tried using the below code

  private JSONObject removeEmpty(JSONObject root) {
    root.keys().forEachRemaining(key -> {
        Object value = root.get(key);
        if (value instanceof JSONObject) {
            removeEmpty((JSONObject) value);
        } else if(value.equals("")) {
            root.remove(key);
        }
    });
    return root;
}

but I am getting a java.util.ConcurrentModificationException error being thrown, and I'm unsure on how to resolve this within a json object. Does anyone have any suggestions in resolving this?

The stack track is

java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1442)
at java.util.HashMap$KeyIterator.next(HashMap.java:1466)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at database.ConvertToJSON.removeEmpty(ConvertToJSON.java:48)
at database.ConvertToJSON.convertToJSON(ConvertToJSON.java:40)
at database.Database.searchByLocation(Database.java:24)
at Application$1.handle(Application.java:30)
at spark.RouteImpl$1.handle(RouteImpl.java:72)
at spark.http.matching.Routes.execute(Routes.java:61)
at spark.http.matching.MatcherFilter.doFilter(MatcherFilter.java:130)
at spark.embeddedserver.jetty.JettyHandler.doHandle(JettyHandler.java:50)
at com.spark.shaded.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1568)
at com.spark.shaded.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at com.spark.shaded.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at com.spark.shaded.eclipse.jetty.server.Server.handle(Server.java:530)
at com.spark.shaded.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:347)
at com.spark.shaded.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:256)
at com.spark.shaded.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at com.spark.shaded.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
at com.spark.shaded.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at com.spark.shaded.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
at com.spark.shaded.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
at com.spark.shaded.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:708)
at com.spark.shaded.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:626)
at java.lang.Thread.run(Thread.java:748)
2
  • 1
    Use an iterator instead of forEachRemaining. Commented Apr 10, 2019 at 11:01
  • The error printout would help if you could provide it? Commented Apr 10, 2019 at 11:12

1 Answer 1

4

You can't remove items from an object while iterating over it as you are doing in your forEachRemaining. You either can mark the items you want to remove (as below) or create a copy to iterate over and remove from the original object.

private JSONObject removeEmpty(JSONObject root) {
    ArrayList<Object> toRemove = new ArrayList<>();
    root.keys().forEachRemaining(key -> {
        Object value = root.get(key);
        if (value instanceof JSONObject) {
            removeEmpty((JSONObject) value);
        } else if(value.equals("")) {
            toRemove.add(key)
        }
    });

    foreach (Object o : toRemove) {
        root.remove((String)o);
    }

    return root;
}

If you get the same error but with regards to the value, you'll need to do the same thing but for the values.

Sign up to request clarification or add additional context in comments.

6 Comments

Hi, just tried that then, but im getting an issue with the remove types, not if if i've missed anything. Thank you btw (java.lang.String) in JSONObject cannot be applied to (java.lang.Object)
Oh yeah sorry, I forgot to cast it to a string. Updated the answer
In Java a foreach loop still uses the for keyword. To be clear, this answer solves the problem, because you can't remove items from an object while iterating over it. You either can mark the items you want to remove (like in the answer) or create a copy to iterate over and remove from the original object.
@TheChubbyPanda hi, this works really well thank you!
No problem, don't forget to mark the answer as the solution so others can find it easily.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.