• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Parson JSON

  • Thread starter Thread starter Deleted User
  • Start date Start date
D

Deleted User

Guest
Could someone point me to a good example for parsing JSON without using GSON?

My JSON string looks like this
[{"name":"value"},{"name":"value"},{"name":"value"}]

I can easily parse if theres just one bracket, but when there are multiple (in this case 3), I'm looking for a good way to do it


Thanks
 
Are you after a generic JSON parser, or do you just want to parse strings like the example you've given?
 
I actually gave you a bad example.

I'm looking for how to use the JSON objects to parse the message. Here is the exact message I'm looking to parse:

Code:
[{"id":"1","delivery_id":"7","subject":"this is test message number one","created_on":"1279303283","isread":"0","summary":"Nam at metus sit amet massa ullamcorper tempus vitae a arcu. Sed pulvinar nunc vel dui porttitor vitae malesuada lorem tristique. Ut at ipsum nec lacus rutrum bibendum vitae quis tellus. Vestibulum a elit est, nec tristique metus. Nam ut neque a enim vest"},{"id":"2","delivery_id":"8","subject":"this is test message number two","created_on":"1279303283","isread":"0","summary":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis suscipit purus. Aliquam erat volutpat. Vivamus iaculis semper ipsum vel commodo. In hac habitasse platea dictumst. Suspendisse potenti. Nullam ut est tortor. Sed accumsan felis a mass"},{"id":"3","delivery_id":"9","subject":"this is test message number three","created_on":"1279303283","isread":"0","summary":"Nam at metus sit amet massa ullamcorper tempus vitae a arcu. Sed pulvinar nunc vel dui porttitor vitae malesuada lorem tristique. Ut at ipsum nec lacus rutrum bibendum vitae quis tellus. Vestibulum a elit est, nec tristique metus. Nam ut neque a enim vest"},{"id":"4","delivery_id":"10","subject":"this is test message number four","created_on":"1273640400","isread":"0","summary":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis suscipit purus. Aliquam erat volutpat. Vivamus iaculis semper ipsum vel commodo. In hac habitasse platea dictumst. Suspendisse potenti. Nullam ut est tortor. Sed accumsan felis a mass"},{"id":"5","delivery_id":"11","subject":"this is test message number five","created_on":"1275368400","isread":"0","summary":"Nam at metus sit amet massa ullamcorper tempus vitae a arcu. Sed pulvinar nunc vel dui porttitor vitae malesuada lorem tristique. Ut at ipsum nec lacus rutrum bibendum vitae quis tellus. Vestibulum a elit est, nec tristique metus. Nam ut neque a enim vest"},{"id":"6","delivery_id":"12","subject":"this is test message number six","created_on":"1277442000","isread":"0","summary":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis suscipit purus. Aliquam erat volutpat. Vivamus iaculis semper ipsum vel commodo. In hac habitasse platea dictumst. Suspendisse potenti. Nullam ut est tortor. Sed accumsan felis a mass"}]
 
Here you go...

Code:
package com.misc.forum;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JsonParser {
	public static void main(String[] args) {
		String json1 = "[{\"name1\":\"value1\"},{\"name2\":\"value2\"},{\"name3\":\"value3\",\"name4\":\"value4\"}]" ;
		String json2 = "[{\"id\":\"1\",\"delivery_id\":\"7\",\"subject\":\"this is test message number one\",\"created_on\":\"1279303283\",\"isread\":\"0\",\"summary\":\"Nam at metus sit amet massa ullamcorper tempus vitae a arcu. Sed pulvinar nunc vel dui porttitor vitae malesuada lorem tristique. Ut at ipsum nec lacus rutrum bibendum vitae quis tellus. Vestibulum a elit est, nec tristique metus. Nam ut neque a enim vest\"},{\"id\":\"2\",\"delivery_id\":\"8\",\"subject\":\"this is test message number two\",\"created_on\":\"1279303283\",\"isread\":\"0\",\"summary\":\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis suscipit purus. Aliquam erat volutpat. Vivamus iaculis semper ipsum vel commodo. In hac habitasse platea dictumst. Suspendisse potenti. Nullam ut est tortor. Sed accumsan felis a mass\"},{\"id\":\"3\",\"delivery_id\":\"9\",\"subject\":\"this is test message number three\",\"created_on\":\"1279303283\",\"isread\":\"0\",\"summary\":\"Nam at metus sit amet massa ullamcorper tempus vitae a arcu. Sed pulvinar nunc vel dui porttitor vitae malesuada lorem tristique. Ut at ipsum nec lacus rutrum bibendum vitae quis tellus. Vestibulum a elit est, nec tristique metus. Nam ut neque a enim vest\"},{\"id\":\"4\",\"delivery_id\":\"10\",\"subject\":\"this is test message number four\",\"created_on\":\"1273640400\",\"isread\":\"0\",\"summary\":\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis suscipit purus. Aliquam erat volutpat. Vivamus iaculis semper ipsum vel commodo. In hac habitasse platea dictumst. Suspendisse potenti. Nullam ut est tortor. Sed accumsan felis a mass\"}]" ;

		List<Map<String,String>> parsedObjects = parseJsonString(json2) ;

		System.out.println("Parsing complete, here are the objects:") ;
		
		int count = parsedObjects.size() ;
		System.out.println("Parsed JSON contained "+count+" objects") ;
		for( Iterator<Map<String,String>> objIter = parsedObjects.iterator(); objIter.hasNext(); ) {
			
			System.out.println("JSON Object:") ;

			Map<String, String> objMap = objIter.next() ;
			
			for( Iterator<String> keyIter = objMap.keySet().iterator(); keyIter.hasNext(); ) {
				String key = keyIter.next() ;
				String val = objMap.get(key) ;
				
				System.out.println("  "+key+" = "+val) ;
			}
		}
	}
	
	public static List<Map<String,String>> parseJsonString(String str) {
		List<Map<String,String>> result = new ArrayList<Map<String,String>>() ;
		
		// Regexp to match multiple occurrences of {.....} separated by commas
		Pattern pattern = Pattern.compile("(\\{.*?\\})((,\\{.*?\\}){0,})") ;
		
		// To simplify code, check that string starts & ends with [] first
		if( !str.startsWith("[") || !str.endsWith("]") ) {
			System.out.println("JSON string doesn't start/end with []") ;
			return result ;
		}
		
		// Middle bit between the [ ... ]
		str = str.substring(1, str.length()-1) ;
		
		Matcher matcher = pattern.matcher(str) ;
		while( matcher != null && matcher.matches() ) {
			String firstObj   = matcher.group(1);
			String restOfObjs = matcher.group(2);
			
			System.out.println("firstObj    = |"+firstObj+"|") ;
			System.out.println("restOfObjs  = |"+restOfObjs+"|") ;
			
			Map<String,String> objMap = parseJsonObject(firstObj) ;
			result.add(objMap) ;
			
			// If the rest of the string isn't null, do regexp on it, skipping initial comma
			if( restOfObjs != null && restOfObjs.length()>0 ) {
				matcher = pattern.matcher(restOfObjs.substring(1)) ;
			}
			else {
				matcher = null ;
			}
		}
		
		return result ;
	}
	
	public static Map<String,String> parseJsonObject(String str) {
		Map<String,String> result = new HashMap<String, String>() ;
		
		Pattern pattern = Pattern.compile("(\".*?\":\".*?\")((,\".*?\":\".*?\"){0,})") ;
		
		System.out.println("Parsing JSON object = |"+str+"|") ;
		
		// Expect string to start/end with {} so check first to make parsing easier
		if( !str.startsWith("{") || !str.endsWith("}") ) {
			System.out.println("JSON object doesn't start/end with {}") ;
			return result ;
		}
		
		str = str.substring(1, str.length()-1) ;

		Matcher matcher = pattern.matcher(str) ;
		while( matcher != null && matcher.matches() ) {
			String firstNameValue  = matcher.group(1);
			String restOfNameValue = matcher.group(2);
			
			System.out.println("  firstNameValue   = |"+firstNameValue+"|") ;
			System.out.println("  restOfNameValue  = |"+restOfNameValue+"|") ;
			
			addNameValueToMap(result,firstNameValue) ;
						
			// If the rest of the string isn't null, do regexp on it, skipping initial comma
			if( restOfNameValue != null && restOfNameValue.length()>0 ) {
				matcher = pattern.matcher(restOfNameValue.substring(1)) ;
			}
			else {
				matcher = null ;
			}
		}

		return result ;
	}
	
	// Take a string of the form:
	//    "name1":"value1"
	// Extract name part "name1", and value part "value1"
	// Add them to the Map
	
	public static void addNameValueToMap(Map<String,String> map, String nameValueStr) {
		Pattern pattern = Pattern.compile("\"(.*?)\":\"(.*?)\"") ;
		Matcher matcher = pattern.matcher(nameValueStr) ;
		
		if( matcher.matches() ) {
			String namePart = matcher.group(1) ;
			String valPart  = matcher.group(2) ;
			
			map.put(namePart, valPart) ;
			System.out.println("    Added name = |"+namePart+"|, value = |"+valPart+"|") ;
		}
		else {
			System.out.println("name/Value pair is not expected syntax: |"+nameValueStr+"|") ;
		}
	}
}

I knocked it up quite quickly, so it might not be the most elegant code.
It's not organised into a reusable class, but that should be easy enough to fix.
The pattern compilation only really needs to be done once for each regexp so those could be moved out and stored as constants.

If you run that with my simple test string json1, which is effectively:
Code:
[{"name1":"value1"},{"name2":"value2"},{"name3":"value3","name4":"value4"}]

It dumps out this output:

Code:
Parsing complete, here are the objects:
Parsed JSON contained 3 objects
JSON Object:
  name1 = value1
JSON Object:
  name2 = value2
JSON Object:
  name3 = value3
  name4 = value4

The parseJsonString method returns a list, with one entry for each JSON object.
(Each thing in curly brackets counts as one object: [ {object-1},{object-2}, etc..])

Each list entry is a Map where the key is a string and the value is a string.
The name/value pairs within an object get turned into a Map.
So "name1":"value1","name2":"value2" becomes 2 entries in the map, one with key "name1" and value "value1", and one with key "name2" and value "value2".


If you run it with the other test string json2, which is the beginning of your example:

Code:
Parsing complete, here are the objects:
Parsed JSON contained 4 objects
JSON Object:
  summary = Nam at metus sit amet massa ullamcorper tempus vitae a arcu. Sed pulvinar nunc vel dui porttitor vitae malesuada lorem tristique. Ut at ipsum nec lacus rutrum bibendum vitae quis tellus. Vestibulum a elit est, nec tristique metus. Nam ut neque a enim vest
  delivery_id = 7
  created_on = 1279303283
  subject = this is test message number one
  id = 1
  isread = 0
JSON Object:
  summary = Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis suscipit purus. Aliquam erat volutpat. Vivamus iaculis semper ipsum vel commodo. In hac habitasse platea dictumst. Suspendisse potenti. Nullam ut est tortor. Sed accumsan felis a mass
  delivery_id = 8
  created_on = 1279303283
  subject = this is test message number two
  id = 2
  isread = 0
JSON Object:
  summary = Nam at metus sit amet massa ullamcorper tempus vitae a arcu. Sed pulvinar nunc vel dui porttitor vitae malesuada lorem tristique. Ut at ipsum nec lacus rutrum bibendum vitae quis tellus. Vestibulum a elit est, nec tristique metus. Nam ut neque a enim vest
  delivery_id = 9
  created_on = 1279303283
  subject = this is test message number three
  id = 3
  isread = 0
JSON Object:
  summary = Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis suscipit purus. Aliquam erat volutpat. Vivamus iaculis semper ipsum vel commodo. In hac habitasse platea dictumst. Suspendisse potenti. Nullam ut est tortor. Sed accumsan felis a mass
  delivery_id = 10
  created_on = 1273640400
  subject = this is test message number four
  id = 4
  isread = 0

I would have run it with the whole of your example, but I got fed up of typing the escape characters in front of all the quotes. (And the line of code was getting huge. Too huge to post here.)

If you're not familiar with regular expressions then it might not be obvious how it works.
It's not helped by using [ ] { } " characters in the JSON string, which are all special characters in regular expressions, so need to be escaped.

The code works with the syntax you used in your example.
If your syntax ends up being different then you'll obviously have to change things.
(e.g. if you're expecting arbitrary whitespace between things, you'll have to cope with that.)

There aren't a lot of comments in the code. Sorry about that. I'd do more but it's late here. (00:25 UK time)

I'll try to help out with explanations if you need them. But maybe not right now.

Mark

p.s.
If you now decide that you really wanted a totally generic parser after all, then this won't be of any use to you. (And I'll have wasted an hour.)
 
Man, I feel so bad, lol. I wrote a little bit of code that split out the JSON to something the JSONObject could understand.

The JSONObject can parse the following two types of JSON strings:
1) {"name":"value"},{"name":"value"},{"name":"value"}
2) {"name":"value","name":"value","name":"value"}

But it can't correctly parse a hybrid of the two:
{"name":"value","name":"value"},{"name":"value","name":"value"}

So what I did was split the overall JSON into a String array of smaller JSON strings like so:

Code:
        try{
        	// if there are beginning and ending
        	// square brackets, be gone with them
        	if(json.startsWith("[")) {
        		json = json.substring(1);
        	}
        	if(json.endsWith("]")) {
        		json = json.substring(0, json.length()-2);
        	}
        	
        	// parse the entire collection into smaller json strings
        	String [] sarray = json.split("\\},\\{");
        	
        	// go through each one and get the data
        	for(int i=0; i<sarray.length; i++) {
        		String jsub = sarray[i];
        		if(!jsub.startsWith("{")) {
        			jsub = "{" + jsub;
        		}
        		if(!jsub.endsWith("}")) {
        			jsub = jsub + "}";
        		}
        		JSONObject jo = new JSONObject(jsub);
        		JSONArray jn = jo.names();
        		JSONArray jv = jo.toJSONArray(jn);
        		
        		for(int x=0; x<jn.length(); x++) {
        			String name = jn.getString(x);
        			String value = jv.getString(x);
        		}
        	}

        }
        catch(JSONException e) {
        	Log.e("json", e.toString());
        }
 
Yeah, that'll do it too. :)

I wasn't aware of the JSONObject class. I should have googled first.

Mark
 
Back
Top Bottom