Print JSON format String


  • 3
    A

    This was a recent interview question. Suppose we have given following string:

    "{"id": "0001", "type": "donut","name": "Cake","ppu": 0.55, "batters":{"batter":[{ "id": "1001", "type": "Regular" },{ "id": "1002", "type": "Chocolate" }]},"topping":[{ "id": "5001", "type": "None" },{ "id": "5002", "type": "Glazed" }]}"
    we need to print it in following order:

    {
    	"id": "0001",
    	"type": "donut",
    	"name": "Cake",
    	"ppu": 0.55,
    	"batters":
    		{
    			"batter":
    				[
    					{ "id": "1001", "type": "Regular" },
    					{ "id": "1002", "type": "Chocolate" }
    				]
    		},
    	"topping":
    		[
    			{ "id": "5001", "type": "None" },
    			{ "id": "5002", "type": "Glazed" }
    		]
    }
    

    Thanks, I updated the formatting. Much better this way. Two things I want to mention, we can assume the string as well formed. And what happens if the string is too long or too deep? Which strategy (stack or single count variable) will be better?

    Sorry folks for the wrong format. I didn't realize before posting. Thanks to https://adobe.github.io/Spry/samples/data_region/JSONDataSetSample.html


  • 0

    The idea is to push in stack number of spaces. We push in stack each time when we encounter [, and pop when we meet ']'
    I assume that there is only one curly parenthesis paar in the string (there is no other JS objects than the main object)
    I also assume that this is JSON without objects {"key":val}
    For element on the same level we peek current element

    void printJSON(String str) {
        Stack<Integer> space = new Stack<>(); 
        int i  = 1;
        int n = str.length() - 1;
        System.out.println(str.charAt(0));
        space.push(2);   
        while (i < n) {    
            int sp = 0;
            if (str.charAt(i) == '[') {   
                sp = space.peek(); 
                space.push(sp + 2);                      
            } 
            else {
                if (str.charAt(i) == ']')   {
                    space.pop();
                    sp = space.peek();
                }
                else {                  
                   sp = space.peek();
                }          
            }  
            while(sp > 0) {
                System.out.print(' ');
                sp--;
            }
            System.out.print(str.charAt(i));
            if ( i < n && str.charAt(i+1) == ',') {
                System.out.print(',');
                i++;
            }
            System.out.println();
            i++;       
        }
        System.out.println(str.charAt(n));
    }
    

  • 2

    @elmirap I think stack is not required in this question.
    A single variable 'spaces' is sufficient which will increment by 1 when '[' is encountered and decrement by 1 on occurence of ']' .


  • 0

    @vinod23 Could you provide your solution pls?Thnks. Probably could be solved and with variable, something like this:

    void printJSON(String str) {
        int space = 2;
        int i  = 1;
        int n = str.length() - 1;
        System.out.println(str.charAt(0));   
        while (i < n) {    
            int sp = 0;
            if (str.charAt(i) == '[') {   
                sp = space;
                space+= 2;                      
            } 
            else {
                if (str.charAt(i) == ']')   {                       
                    space  = space - 2;
                   sp = space ;  
                }
                else {                  
                   sp =  space;
                }          
            }  
            while(sp > 0) {
                System.out.print(' ');
                sp--;
            }
            System.out.print(str.charAt(i));
            if ( i < n && str.charAt(i+1) == ',') {
                System.out.print(',');
                i++;
            }
            System.out.println();
            i++;       
        }
        System.out.println(str.charAt(n));
    }
    

  • -1

    @elmirap
    Python Solution

    s=raw_input()
    spaces=2
    t=''
    for ch in s:
    	if ch==' ':
    		continue
    	if ch=='[':
    		print spaces*' '+ch
    		spaces+=2
    	elif ch==']':
    		if t!='':
    			print spaces*' '+t
    		        t=''
    		spaces-=2
    		print spaces*' '+ch
    	elif ch==',':
    		if t=='':`
    			print ch
    		else:
    			print spaces*' '+t+','
    			t=''
    	elif ch=='{' or ch=='}':
    		print ch	 
    	else:
    		t+=ch
    

  • 0

    @vinod23 thanks


  • 0
    A

    @1337c0d3r thanks, I updated it.


  • 0

    @agrawalm we don't need stack as @vinod23 suggested because there is a relation between number of spaces of outer and inner level, e.g there is a formule


  • 1

    @agrawalm said in Print JSON format String:

    we can assume the string as well formed

    Your example string is not even close to well formed, though.


  • 0
    This post is deleted!

  • 0

    I think that this example is not even close to what JSON is. At least we don't have objects in the example, only arrays, also it is not clear which alphabet is acceptable.


  • 0
    A

    @StefanPochmann my bad, updated with a "correct" json. Thanks for pointing that out.


  • 0

    @agrawalm thank you very much. I am afraid that code above should be reworked


  • 0
    N
    dictliststart = ["{", "["]
    dictlistend = ["]", "}"]
    newLineTriggers = dictliststart + dictlistend
    
    space = 0
    for s in jstr:
        if not s.strip():
            continue
        s = s.strip()
        # if list/object start or end add new line
        if s in newLineTriggers:        
            # for obj/list end remove 4 spaces 
            if s in dictlistend:
                space -= 4
                print("\n" + " " * space + s, end="", flush=True)
    
            # for obj/list start add 4 spaces 
            else:
                print(s, end="", flush=True)
                space += 4
                
            print("\n"+ " " * space, end="")
        elif s = ",":
            print(s, end="\n" + " " * space, flush=True)        
        else:
            print(s, end="", flush=True)
    

  • 0
    L

    My Java solution.

            void printJsonString(String jsonStr){
    		if(jsonStr == null || jsonStr.trim().length() == 0){
    			System.out.println(jsonStr);
    			return;
    		}
    		final String ret = "\n";
    		StringBuilder formattedJson = new StringBuilder();
    		StringBuilder spaces = new StringBuilder();
    		Deque<Character> stack = new ArrayDeque<>();
    		for(int i=0; i<jsonStr.length(); ){
    			char c = jsonStr.charAt(i);
    			switch(c){
    			case '{':
    			case '[':
    				stack.push(c);
    				spaces.append("\t");
    				formattedJson.append(c).append(ret).append(spaces);
    				i++;
    				break;
    			case '}':
    			case ']':
    				stack.pop();
    				spaces.deleteCharAt(spaces.length()-1);
    				formattedJson.append(ret).append(spaces).append(c);
    				i++;
    				if(!(i<jsonStr.length() && jsonStr.charAt(i) == ',')){
    					formattedJson.append(ret).append(spaces);
    				}
    				break;
    			case ',':
    				formattedJson.append(c).append(ret).append(spaces);
    				i++;
    				break;
    			default:
    				formattedJson.append(c);
    				i++;
    				break;
    			}
    		}
    		System.out.println(formattedJson);
    	}
    

  • 0
    J

    Python solution using regular expressions

    from collections import deque
    import re
    import sys
    
    def print_json(json):
        level = 0
        strs = re.findall(r'[\{\[]*[\"\w\:\,\s\.]+[\]\}\,]*', json)
        i = 1
        while i < len(strs)/2+1:
            if strs[i][0] == '{' or strs[i][0] == '[':
                if strs[i][0] == '[':
                    sys.stdout.write(strs[i][0])
                    strs[i] = strs[i][1:]
                    level += 1
                    sys.stdout.write('\n')
                    sys.stdout.write(level * '\t')
                    continue
                level+=1
                sys.stdout.write(strs[i][0])
                sys.stdout.write('\n')
                sys.stdout.write(level * '\t')
            for ch in strs[i][1:]:
                if ch == ',':
                    sys.stdout.write(ch)
                    sys.stdout.write('\n')
                    sys.stdout.write(level * '\t')
                    continue
                if ch == '}' or ch == ']':
                    sys.stdout.write('\n')
                    level -= 1
                    sys.stdout.write(level*'\t')
                sys.stdout.write(ch)
            i+=1
        print '\n'
    
    print_json(json_str)

  • 0
    I

    Was this phone or onsite interview?


  • 0
    I

    @vinod23 If the character is ']', why do you need a cahse where if t != ''? If it is valid json wouldn't this always be true? Same for if the character is a comma, the t cannot be '', right?


  • 0
    A

    @IWantToPass this was during onsite. In the light coding round (if you are familiar with fb interview round called Jedi)


  • 1
    I

    @agrawalm I see. DId you hear back yet?


Log in to reply
 

Looks like your connection to LeetCode Discuss was lost, please wait while we try to reconnect.