Open Source Repository

Home /json/json-lib-2.4-jdk15 | Repository Home


net/sf/json/groovy/JsonGroovyBuilder.java
/*
 * Copyright 2002-2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.sf.json.groovy;

import groovy.lang.Closure;
import groovy.lang.GString;
import groovy.lang.GroovyObjectSupport;
import groovy.lang.MissingMethodException;

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

import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

/**
 * A Groovy builder for JSON values.
 *
 <pre>
def books1 = builder.books {
   book = [title: "The Definitive Guide to Grails", author: "Graeme Rocher"]
   book = [title: "The Definitive Guide to Grails", author: "Graeme Rocher"]
}

def books2 = builder.books {
   book = new Book(title: "The Definitive Guide to Grails",
                   author: "Graeme Rocher")
   book = new Book(title: "The Definitive Guide to Grails",
                   author: "Graeme Rocher")
}

def books3 = builder.books {
   book = {
      title = "The Definitive Guide to Grails"
      author= "Graeme Rocher"
   }
   book = {
      title = "The Definitive Guide to Grails"
      author= "Graeme Rocher"
   }
}

def books4 = builder.books {
   book {
      title = "The Definitive Guide to Grails"
      author= "Graeme Rocher"
   }
   book {
      title = "The Definitive Guide to Grails"
      author= "Graeme Rocher"
   }
}

def books5 = builder.books {
   2.times {
      book = {
         title = "The Definitive Guide to Grails"
         author= "Graeme Rocher"
      }
   }
}

def books6 = builder.books {
   2.times {
      book {
         title = "The Definitive Guide to Grails"
         author= "Graeme Rocher"
      }
   }
}


 all 6 books variables output the same JSON

{"books": {
   "book": [{
         "title": "The Definitive Guide to Grails",
         "author": "Graeme Rocher"
      },{
         "title": "The Definitive Guide to Grails",
         "author": "Graeme Rocher"
      }]
   }
}
</pre>
 *
 @author Andres Almiray <[email protected]>
 */
public class JsonGroovyBuilder extends GroovyObjectSupport {
   private static final String JSON = "json";
   private JSON current;
   private Map properties;
   private Stack stack;

   public JsonGroovyBuilder() {
      stack = new Stack();
      properties = new HashMap();
   }

   public Object getPropertyString name ) {
      if!stack.isEmpty() ){
         Object top = stack.peek();
         iftop instanceof JSONObject ){
            JSONObject json = (JSONObjecttop;
            ifjson.containsKeyname ) ){
               return json.getname );
            }else{
               return _getPropertyname );
            }
         }else{
            return _getPropertyname );
         }
      }else{
         return _getPropertyname );
      }
   }

   public Object invokeMethodString name, Object arg ) {
      ifJSON.equalsname && stack.isEmpty() ){
         return createObjectname, arg );
      }

      Object[] args = (Object[]) arg;
      ifargs.length == ){
         throw new MissingMethodExceptionname, getClass(), args );
      }

      Object value = null;
      ifargs.length > ){
         JSONArray array = new JSONArray();
         stack.pusharray );
         forint i = 0; i < args.length; i++ ){
            ifargs[iinstanceof Closure ){
               appendname, createObject( (Closureargs[i] ) );
            }else ifargs[iinstanceof Map ){
               appendname, createObject( (Mapargs[i] ) );
            }else ifargs[iinstanceof List ){
               appendname, createArray( (Listargs[i] ) );
            }else{
               _appendname, args[i](JSONstack.peek() );
            }
         }
         stack.pop();
      }else{
         ifargs[0instanceof Closure ){
            value = createObject( (Closureargs[0] );
         }else ifargs[0instanceof Map ){
            value = createObject( (Mapargs[0] );
         }else ifargs[0instanceof List ){
            value = createArray( (Listargs[0] );
         }
      }

      ifstack.isEmpty() ){
         JSONObject object = new JSONObject();
         object.accumulatename, current );
         current = object;
      }else{
         JSON top = (JSONstack.peek();
         iftop instanceof JSONObject ){
            appendname, current == null ? value : current );
         }
      }

      return current;
   }

   public void setPropertyString name, Object value ) {
      ifvalue instanceof GString ){
         value = value.toString();
         try{
            value = JSONSerializer.toJSONvalue );
         }catchJSONException jsone ){
            // its a String literal
         }
      }else ifvalue instanceof Closure ){
         value = createObject( (Closurevalue );
      }else ifvalue instanceof Map ){
         value = createObject( (Mapvalue );
      }else ifvalue instanceof List ){
         value = createArray( (Listvalue );
      }

      appendname, value );
   }

   private Object _getPropertyString name ) {
      ifproperties.containsKeyname ) ){
         return properties.getname );
      }else{
         return super.getPropertyname );
      }
   }

   private void appendString key, Object value ) {
      Object target = null;
      if!stack.isEmpty() ){
         target = stack.peek();
         current = (JSONtarget;
         _appendkey, value, current );
      }else{
         properties.putkey, value );
      }
   }

   private void _appendString key, Object value, JSON target ) {
      iftarget instanceof JSONObject ){
         ((JSONObjecttarget).accumulatekey, value );
      }else iftarget instanceof JSONArray ){
         ((JSONArraytarget).elementvalue );
      }
   }

   private JSON createArrayList list ) {
      JSONArray array = new JSONArray();
      stack.pusharray );
      forIterator elements = list.iterator(); elements.hasNext()){
         Object element = elements.next();
         ifelement instanceof Closure ){
            element = createObject( (Closureelement );
         }else ifelement instanceof Map ){
            element = createObject( (Mapelement );
         }else ifelement instanceof List ){
            element = createArray( (Listelement );
         }
         array.elementelement );
      }
      stack.pop();
      return array;
   }

   private JSON createObjectClosure closure ) {
      JSONObject object = new JSONObject();
      stack.pushobject );
      closure.setDelegatethis );
      closure.setResolveStrategyClosure.DELEGATE_FIRST );
      closure.call();
      stack.pop();
      return object;
   }

   private JSON createObjectMap map ) {
      JSONObject object = new JSONObject();
      stack.pushobject );
      forIterator properties = map.entrySet()
            .iterator(); properties.hasNext()){
         Map.Entry property = (Map.Entryproperties.next();
         String key = String.valueOfproperty.getKey() );
         Object value = property.getValue();
         ifvalue instanceof Closure ){
            value = createObject( (Closurevalue );
         }else ifvalue instanceof Map ){
            value = createObject( (Mapvalue );
         }else ifvalue instanceof List ){
            value = createArray( (Listvalue );
         }
         object.elementkey, value );
      }
      stack.pop();
      return object;
   }

   private JSON createObjectString name, Object arg ) {
      Object[] args = (Object[]) arg;
      ifargs.length == ){
         throw new MissingMethodExceptionname, getClass(), args );
      }

      ifargs.length == ){
         ifargs[0instanceof Closure ){
            return createObject( (Closureargs[0] );
         }else ifargs[0instanceof Map ){
            return createObject( (Mapargs[0] );
         }else ifargs[0instanceof List ){
            return createArray( (Listargs[0] );
         }else{
            throw new JSONException"Unsupported type" );
         }
      }else{
         JSONArray array = new JSONArray();
         stack.pusharray );
         forint i = 0; i < args.length; i++ ){
            ifargs[iinstanceof Closure ){
               appendname, createObject( (Closureargs[i] ) );
            }else ifargs[iinstanceof Map ){
               appendname, createObject( (Mapargs[i] ) );
            }else ifargs[iinstanceof List ){
               appendname, createArray( (Listargs[i] ) );
            }else{
               _appendname, args[i](JSONstack.peek() );
            }
         }
         stack.pop();
         return array;
      }
   }
}