Instead of using the split function, you can convert your String to a JSONArray and then iterate throw the array
JSONArray jsonArray = new JSONArray(response.toString());
for(int i=0; i<jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String jsonObjectAsString = jsonObject.toString();
}
Answer from ThomasThiebaud on Stack OverflowYou can use subList method:
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class JsonApp {
public static void main(String[] args) {
List<Integer> ints = IntStream.range(1, 10).boxed().collect(Collectors.toList());
JsonArrayExt array = new JsonArrayExt(ints);
JsonArray array1 = array.subList(2, 5);
System.out.println(array);
System.out.println(array1);
}
}
class JsonArrayExt {
private final JsonArray array;
public JsonArrayExt(List<Integer> ints) {
this(Json.createArrayBuilder(ints).build());
}
public JsonArrayExt(JsonArray array) {
this.array = Objects.requireNonNull(array);
}
public JsonArray subList(int fromIndex, int toIndex) {
JsonArrayBuilder builder = Json.createArrayBuilder();
array.subList(fromIndex, toIndex).forEach(builder::add);
return builder.build();
}
@Override
public String toString() {
return array.toString();
}
}
Above code prints:
[1,2,3,4,5,6,7,8,9]
[3,4,5]
with Gson
List<MyModel> myModelList = gson.fromJson(jsonArray.toString(), listType);
Updated
you can create a utility for the same if you only want to use javax.json package. Below is the complete sample code with only javax.json.* package.
import java.io.StringReader; import java.util.List;
import javax.json.Json; import javax.json.JsonArray; import javax.json.JsonObject; import javax.json.JsonReader; import javax.json.JsonValue;
public class Converter {
public static void main(String[] args) {
String str = "{\r\n" +
"\"name\":\"John\",\r\n" +
"\"age\":30,\r\n" +
"\"cars\":[ \"Ford\", \"BMW\", \"Fiat\" ]\r\n" +
"}";
JsonReader reader = Json.createReader(new StringReader(str));
JsonObject object = reader.readObject();
JsonArray array = object.getJsonArray("cars");
System.out.println(getJsonArrayFromIndex(1, 2, array));
System.out.println(getJsonArrayFromIndex(0, 2, array));
System.out.println(getJsonArrayFromIndex(0, 1, array));
}
public static List<JsonValue> getJsonArrayFromIndex(int start, int end, JsonArray array) {
return array.subList(start, end);
}
}
output
[BMW]
[Ford, BMW]
[Ford]
Well, I'm a little ashamed to post this code. It's not optimal at all, looks awful, but probably it could lead you to right direction if you want completely unaltered content.
enum ParserState {
READING_OBJECT,
READING_ARRAY
}
public static List<String> extractObjects(String array) throws ParseException {
ParserState state = ParserState.READING_ARRAY;
ArrayList<String> result = new ArrayList<String>();
StringBuilder currentObject = null;
int i = 0;
int parenthesisBalance = 0;
for (char c : array.toCharArray()) {
switch (c) {
case '{': {
if (state == ParserState.READING_ARRAY) {
state = ParserState.READING_OBJECT;
currentObject = new StringBuilder();
}
parenthesisBalance++;
currentObject.append(c);
break;
}
case '}': {
if (state == ParserState.READING_ARRAY) {
throw new ParseException("unexpected '}'", i);
} else {
currentObject.append(c);
parenthesisBalance--;
if (parenthesisBalance == 0) {
state = ParserState.READING_ARRAY;
result.add(currentObject.toString());
}
}
break;
}
default: {
if (state == ParserState.READING_OBJECT) {
currentObject.append(c);
}
}
}
i++;
}
return result;
}
Try the code below using GSON Lib - you can put json objects also instead of string LOCATION
public static void main(String[] args) {
String obj = "{'id':'joe','ts':'2014-12-02T13:58:23.801+0100','foo':{'bar':{'v1':50019820,'v2':0, 'v3':0.001, 'v4':-100, 'v5':0.000001, 'v6':0.0, 'b':true}}}".replace("'", "\"");
String string = String.format("[%s,%s,%s,%s]", obj , obj , obj , obj );
JsonParser parser = new JsonParser();
JsonArray arr = (JsonArray)parser.parse(string);
//JsonArray arr = o.getAsJsonArray();
Iterator<JsonElement> itr = arr.iterator();
while(itr.hasNext()){
JsonElement val = itr.next();
System.out.println(val);
}
}
A nice solution for this problem is simply to iterate by using the Java 8 Streaming API:s. The JsonNode object is Iterable where the spliterator method is available. So, the following code can be used:
public List<String> split(final String jsonArray) throws IOException {
final JsonNode jsonNode = new ObjectMapper().readTree(jsonArray);
return StreamSupport.stream(jsonNode.spliterator(), false) // Stream
.map(JsonNode::toString) // map to a string
.collect(Collectors.toList()); and collect as a List
}
Another alternative is to skip the remapping (the call to toString) and return a List<JsonNode> elements instead. That way you can use the JsonNode methods to access the data (get, path and so on).
Finally, I found a solution that works:
public List<String> split(String jsonArray) throws Exception {
List<String> splittedJsonElements = new ArrayList<String>();
ObjectMapper jsonMapper = new ObjectMapper();
JsonNode jsonNode = jsonMapper.readTree(jsonArray);
if (jsonNode.isArray()) {
ArrayNode arrayNode = (ArrayNode) jsonNode;
for (int i = 0; i < arrayNode.size(); i++) {
JsonNode individualElement = arrayNode.get(i);
splittedJsonElements.add(individualElement.toString());
}
}
return splittedJsonElements;
}
You can create an instance of org.json.JSONArray with server response:
String serverResponse = "YOUR STRING";
JSONArray serverJsonArray = new JSONArray(serverResponse);
And then fill products list:
ArrayList<String> products = new ArrayList<>(serverJsonArray.length());
for(int i = 0; i < serverJsonArray.length(); i++){
products.add(serverJsonArray.getString(i));
}
Or if you absolutely want a String array:
String[] products = new String[serverJsonArray.length()];
for(int i = 0; i < serverJsonArray.length(); i++){
products[i] = serverJsonArray.getString(i);
}
Looks like a JSONArray? I suggest using the json objects to get a string array out of this and then do with it whatever you want. There are some ways to do that and there are a lot of examples out there.
To split a json with many records into chunks of a desired size I simply use:
jq -c '.[0:1000]' mybig.json
which works like python slicing.
See the docs here: https://stedolan.github.io/jq/manual/
Array/String Slice: .[10:15]
The .[10:15] syntax can be used to return a subarray of an array or substring of a string. The array returned by .[10:15] will be of length 5, containing the elements from index 10 (inclusive) to index 15 (exclusive). Either index may be negative (in which case it counts backwards from the end of the array), or omitted (in which case it refers to the start or end of the array).
Using jq, one can split an array into its components using the filter:
.[]
The question then becomes what is to be done with each component. If you want to direct each component to a separate file, you could (for example) use jq with the -c option, and filter the result into awk, which can then allocate the components to different files. See e.g. Split JSON File Objects Into Multiple Files
Performance considerations
One might think that the overhead of calling jq+awk would be high compared to calling python, but both jq and awk are lightweight compared to python+json, as suggested by these timings (using Python 2.7.10):
time (jq -c .[] input.json | awk '{print > "doc00" NR ".json";}')
user 0m0.005s
sys 0m0.008s
time python split.py
user 0m0.016s
sys 0m0.046s
You could do something like this:
public static void main(String[] args) throws IOException {
String summary = "";
for(int a = 0; a<100000; a++) {
String current = "\r\n" + new ObjectMapper().writeValueAsString(new MyClass());
if((summary + current).getBytes("UTF-8").length>100000) {
System.out.println("Overload 100 kb!");
printFile(summary);
summary = current;
}
else
summary = summary + "\r\n" + new ObjectMapper().writeValueAsString(new MyClass());
}
}
public static void printFile(String string) throws IOException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss_SSS");
try( PrintWriter out = new PrintWriter("C:\\Chunks\\" +sdf.format(new Date()) +".txt" ) ){
out.println( string );
}
}
Consider UTF-8 as a choice. Split happens taking count the byte[] lenght so 100000 byte are 100kb.
For the serialization I've used a standard Jackson approach, this is the maven dependency:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.3</version>
</dependency>
...and finally the simple Pojo class:
public class MyClass implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public String getField2() {
return field2;
}
public void setField2(String field2) {
this.field2 = field2;
}
public MyClass() {
super();
// TODO Auto-generated constructor stub
}
private String field1;
private String field2;
//getter and setter
}
Let me know if it helps!
The exact implementation may depend on the serialization framework used (have a look at Jackson, it is pretty easy to use), some may offer a specialized streaming API that can achieve something like this. In the scenario that you are describing, a much simpler solution could be used though:
Serialize each instance in a for-loop and collect Strings in a buffer (e.g. StringBuilder or you go straight to an OutputStream). However, before you append a String to this buffer, you can check if size of your buffer + size of the new String exceed the 100kb. The only piece missing now are a few characters for start ( [ ), separator ( , ) and end ( ] )
(For the size calculations to be correct, you may have to convert the strings to bytes since characters like Äφς will take up more than one byte. Maybe this is already handled by your JSON framework)
You could of course do the serialization manually, but especially if your strings can contain characters like quotes ( " ) you could end up writing a lot of code until the JSON format is correct.
[edith: as others have pointed out, if the strings could be longer than 100kb it is not really possible to follow the specification]