iing.uabc.edu.mx.persistencia.util.JSON.java Source code

Java tutorial

Introduction

Here is the source code for iing.uabc.edu.mx.persistencia.util.JSON.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package iing.uabc.edu.mx.persistencia.util;

import iing.uabc.edu.mx.persistencia.modelo.Contexto;
import iing.uabc.edu.mx.persistencia.modelo.Proceso;
import iing.uabc.edu.mx.persistencia.modelo.Recurso;
import iing.uabc.edu.mx.persistencia.modelo.Registro;
import iing.uabc.edu.mx.persistencia.modelo.Usuario;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.json.Json;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import javax.xml.bind.DatatypeConverter;
import org.apache.commons.lang3.time.DateFormatUtils;
import test.TestPojo;

/**
 * Restrictions: The bean has to follow the java bean naming convention for
 * fields and accesors. If the bean throws some kind of lazy exception when
 * reading a field, it has to be from Hibernate.
 *
 * Every entity has to have a primary key field if you are planning to map
 * bidirectional associations. The name for this field has to be 'id' if you are
 * using xml mapping files instead of annotations.
 *
 * You cannot parse a json array containing not domain specific pojos directly.
 * Example: String, ArrayList, etc.
 *
 * When parsing a json String, the .class has to be the most specific one that
 * is represented by the json String.
 *
 * There cannot be arrays inside of arrays, nor domain pojos that declare
 * Collections of Collections, it can only be a collection of domain pojos,
 * containing another collection of domain pojos, String or primitive types, and
 * so on.
 *
 * The declared collections inside pojos has to be declared explicitly with the
 * class of the elements contained in the collection. Example: instead of List
 * elements = new List(); use List<Element> elements = new List<>(); You also
 * need to create new instances of collections right from the beginning in each
 * pojo instance.
 *
 * There cannot be collections of different element types, (Polymorphic), unless
 * every element shares exactly the same attribute names, so there will be no
 * problem with the parsing.
 *
 * @version 1
 * @author donniestorm
 */
public class JSON {

    public static <T> Object parse(String jsonString, Class<T> clazz) {
        //The resulting object represented as the json String
        Object result = null;

        try ( //For reading all the json string tree
                JsonParser parser = Json.createParser(new StringReader(jsonString))) {

            System.out.println("------------------Parsing Start--------------------");
            Event evt = parser.next();
            if (evt == Event.START_OBJECT) {
                System.out.println("Nuevo Objeto: " + clazz.getSimpleName());

                //Prepare POJO for json to POJO parsing
                BeanManager<T> manager = new BeanManager<>(clazz);
                //Is an object
                result = parseObject(parser, manager);
            } else if (evt == Event.START_ARRAY) {
                //Is an array
                System.out.println("Nueva Colleccion de clase: " + clazz.getSimpleName());

                //Prepare collection for json to Collection parsing
                CollectionManager<T> manager = new CollectionManager<>(new ArrayList<>(), clazz);

                result = parseArray(parser, manager);
            }

            System.out.println("------------------Parsing End--------------------");
        }

        return result;
    }

    private static Object parseObject(JsonParser parser, BeanManager manager) {
        Event evt;
        String keyName = "";

        do {
            evt = parser.next();

            switch (evt) {
            case START_OBJECT:
                Class objectClass = manager.getType(keyName);
                System.out.println("Nuevo Objeto: " + objectClass.getSimpleName());
                //Create new BeanManager for the new object with its class
                BeanManager objectManager = new BeanManager(objectClass);

                Object result = parseObject(parser, objectManager);

                manager.setProperty(keyName, result);
                break;

            case START_ARRAY:
                //Get element class of the collection
                Class elementClass = manager.getCollectionElementType(keyName);

                System.out.println("Nueva Colleccion de clase: " + elementClass.getSimpleName());

                //Get collection instance from the bean
                Collection collection = (Collection) manager.getProperty(keyName);

                //Create new collection manager with the given class
                CollectionManager collectionManager = new CollectionManager(collection, elementClass);

                collection = parseArray(parser, collectionManager);

                manager.setProperty(keyName, collection);
                break;

            case KEY_NAME:
                //Get attribute name
                keyName = parser.getString();
                System.out.println("KeyName: " + keyName);
                break;

            case VALUE_FALSE:
                manager.setProperty(keyName, false);
                System.out.println("Valor " + keyName + ": " + false);
                break;

            case VALUE_NULL:
                manager.setProperty(keyName, null);
                System.out.println("Valor " + keyName + ": null");
                break;

            case VALUE_NUMBER:
                //double or int
                if (parser.isIntegralNumber()) {
                    int value = parser.getInt();
                    manager.setProperty(keyName, value);
                    System.out.println("Valor " + keyName + ": " + value);
                } else {
                    double value = parser.getBigDecimal().doubleValue();
                    manager.setProperty(keyName, value);
                    System.out.println("Valor " + keyName + ": " + value);
                }
                break;

            case VALUE_STRING:
                String value = parser.getString();

                //Validate if the field is of type Date
                if (manager.getType(keyName) == Date.class) {
                    Calendar cal = DatatypeConverter.parseDateTime(value);
                    Date date = cal.getTime();
                    manager.setProperty(keyName, date);

                    System.out.println("Valor " + keyName + ": " + date);
                } else {
                    manager.setProperty(keyName, value);
                    System.out.println("Valor " + keyName + ": " + value);
                }
                break;
            case VALUE_TRUE:
                manager.setProperty(keyName, true);
                System.out.println("Valor " + keyName + ": " + true);
                break;
            }
        } while (evt != Event.END_OBJECT);

        return manager.getBean();
    }

    private static Collection parseArray(JsonParser parser, CollectionManager manager) {

        Event evt;
        Class elementClass = manager.getElementClass();
        int pos = 0;

        do {
            evt = parser.next();

            switch (evt) {
            case START_OBJECT:
                //The most expected case of all in an array
                System.out.println(
                        "Nuevo Objeto: " + elementClass.getSimpleName() + " del arreglo en la pos: " + pos);

                BeanManager objectManager = new BeanManager(elementClass);

                Object result = parseObject(parser, objectManager);

                manager.addElement(result);
                pos++;

                break;

            //                case START_ARRAY:
            //                    //Only possible if array of arrays in json which is unlikely
            //                    //Also if in the pojo there is a recursive collection diferent
            //                    //from arraylist then there will be some problems.
            //                    
            ////                    System.out.println("Nueva Colleccion de clase: " + 
            ////                            elementClass.getSimpleName() + "dentro de otro "
            ////                            + "arreglo en la pos: " + pos);
            ////                    
            ////                    CollectionManager<T> collectionManager = new 
            ////                        CollectionManager<>(new ArrayList<>(), elementClass);
            ////                    
            ////                    Collection<T> collection = parseArray(parser, collectionManager);
            ////                    manager.addElement(collection);
            ////                    pos++;
            //                    break;
            //if it is an array of booleans.... but no.
            case VALUE_FALSE:
                System.out.println("Agregando false al arreglo en la pos: " + pos);

                manager.addElement(false);
                pos++;
                break;

            case VALUE_NULL:
                System.out.println("Agregando null al arreglo en la pos: " + pos);

                manager.addElement(null);
                pos++;
                break;

            case VALUE_NUMBER:
                //double or int
                if (parser.isIntegralNumber()) {
                    int value = parser.getInt();
                    System.out.println("Agregando " + value + " al arreglo en la pos: " + pos);

                    manager.addElement(value);
                    pos++;
                } else {
                    double value = parser.getBigDecimal().doubleValue();
                    System.out.println("Agregando " + value + " al arreglo en la pos: " + pos);

                    manager.addElement(value);
                    pos++;
                }
                break;

            case VALUE_STRING:
                String value = parser.getString();

                //Validate if the field is of type Date
                if (manager.getElementClass() == Date.class) {
                    Calendar cal = DatatypeConverter.parseDateTime(value);
                    Date date = cal.getTime();

                    System.out.println("Agregando " + date + " al arreglo en la pos: " + pos);

                    manager.addElement(date);
                    pos++;
                } else {
                    System.out.println("Agregando " + value + " al arreglo en la pos: " + pos);

                    manager.addElement(value);
                    pos++;
                }
                break;
            case VALUE_TRUE:
                System.out.println("Agregando true al arreglo en la pos: " + pos);

                manager.addElement(true);
                pos++;
                break;
            }
        } while (evt != Event.END_ARRAY);

        return manager.getCollection();
    }

    public static String stringify(Object data) {
        StringWriter writer = new StringWriter();
        //Multiple objects has to be in a collection, not an array
        try (JsonGenerator generator = Json.createGenerator(writer)) {

            System.out.println("------------------Stringify Start--------------------");
            //Multiple objects has to be in a collection, not an array
            if (data instanceof Collection) {

                CollectionManager collectionManager = new CollectionManager((Collection) data, data.getClass());

                System.out.println("Nueva Colleccion [] de clase: " + data.getClass().getSimpleName());

                generator.writeStartArray();

                stringifyArray(generator, collectionManager);

                generator.writeEnd();

            } else {
                //A regular object
                BeanManager manager = new BeanManager(data);

                System.out.println("Nuevo Objecto {}: " + data.getClass().getSimpleName());
                generator.writeStartObject();

                stringifyObject(generator, manager);

                generator.writeEnd();
            }

            System.out.println("------------------Stringify End--------------------");
        }

        return writer.toString();
    }

    private static void stringifyObject(JsonGenerator generator, BeanManager manager) {

        String keyName;

        Field[] fields = manager.getFields();

        //Read every field and transform  it to a json property string
        for (Field field : fields) {
            Class fieldType = manager.getType(field.getName());
            keyName = field.getName();
            Object value = manager.getProperty(keyName);

            System.out.println("KeyName: " + keyName);
            System.out.println("Valor " + keyName + ": " + value);

            if (value == null) {
                //Set to null the property
                generator.writeNull(keyName);
                continue;
            }
            //Is a String
            if (fieldType == String.class) {
                generator.write(keyName, String.valueOf(value));
            } //Is a Date
            else if (fieldType == Date.class) {
                String date = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(value);

                generator.write(keyName, date);

            } //Is a integer
            else if (fieldType == Integer.class || fieldType == Integer.TYPE) {
                generator.write(keyName, (int) value);
            } //Is a double
            else if (fieldType == Double.class || fieldType == Double.TYPE) {
                generator.write(keyName, (double) value);
            } //Is boolean
            else if (fieldType == Boolean.class || fieldType == Boolean.TYPE) {
                generator.write(keyName, (boolean) value);
            } //Is a collection
            else if (value instanceof Collection) {
                Class elementClass = manager.getCollectionElementType(keyName);

                System.out.println("Nueva Colleccion [] de clase: " + elementClass.getSimpleName());

                generator.writeStartArray(keyName);

                //Create new collection manager with the given class
                CollectionManager collectionManager = new CollectionManager((Collection) value, elementClass);

                stringifyArray(generator, collectionManager);

                generator.writeEnd();
            } else {
                //Is a object... probably
                BeanManager objectManager = new BeanManager(value);

                System.out.println("Nuevo Objecto {}: " + value.getClass().getSimpleName());
                generator.writeStartObject(keyName);

                stringifyObject(generator, objectManager);

                generator.writeEnd();
            }
        }

    }

    public static void stringifyArray(JsonGenerator generator, CollectionManager manager) {

        //Get size of the array to start stringifying elements
        //Note that the elements of this array has to be of the same class
        Collection collection = manager.getCollection();
        Class elementType = manager.getElementClass();

        System.out.println("Coleccion de tamanio " + collection.size());

        int i = 0;
        //Read every element and transform  it to a json array element string
        for (Iterator it = collection.iterator(); it.hasNext();) {
            Object element = it.next();

            System.out.println("Elemento: [" + i + "], Valor: " + element);

            if (element == null) {
                //Set to null the property
                generator.writeNull();
                continue;
            }

            //Is a String
            if (elementType == String.class) {
                generator.write(String.valueOf(element));
            } //Is a Date
            else if (elementType == Date.class) {
                String date = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(element);

                generator.write(date);

            } //Is a integer
            else if (elementType == Integer.class || elementType == Integer.TYPE) {
                generator.write((int) element);
            } //Is a double
            else if (elementType == Double.class || elementType == Double.TYPE) {
                generator.write((double) element);
            } //Is boolean
            else if (elementType == Boolean.class || elementType == Boolean.TYPE) {
                generator.write((boolean) element);

            } //Is a collection (Not implemented)
            else if (element instanceof Collection) {
                //                Class elementClass = manager.getCollectionElementType(keyName);
                //
                //                System.out.println("Nueva Colleccion [] de clase: "
                //                        + elementClass.getSimpleName());
                //
                //                generator.writeStartArray(keyName);
                //
                //                //Create new collection manager with the given class
                //                CollectionManager collectionManager
                //                        = new CollectionManager((Collection) value, elementClass);
                //
                //                generator.writeEnd();
            } else {
                //Is a object... probably
                BeanManager objectManager = new BeanManager(element);

                System.out.println("Nuevo Objecto {}: " + element.getClass().getSimpleName());
                generator.writeStartObject();

                stringifyObject(generator, objectManager);

                generator.writeEnd();
            }
        }
    }

    public static void main(String[] args) {
        TestPojo tp = new TestPojo();

        tp.setId(1);
        tp.setName("lel");
        tp.setOk(true);
        List<Recurso> recursos = new ArrayList<>();

        recursos.add(new Recurso("hohoho"));
        recursos.add(new Recurso("http://www,com"));
        recursos.add(new Recurso("Relatorio.com"));

        tp.setRecursos(recursos);

        String test = JSON.stringify(new Registro(new Contexto("page"), new Proceso("busq-enc"),
                new Recurso("*.com"), new Usuario("donnie", "pass"), new Date()));

        JSON.parse(test, Registro.class);

        System.out.println(JSON.stringify(tp));

        System.out.println(test);

        JSON.parse(JSON.stringify(tp), TestPojo.class);

        System.out.println(JSON.stringify(recursos));

        JSON.parse(JSON.stringify(recursos), Recurso.class);
    }
}