com.heliosapm.tsdblite.json.JSON.java Source code

Java tutorial

Introduction

Here is the source code for com.heliosapm.tsdblite.json.JSON.java

Source

/*
 * Copyright 2015 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 com.heliosapm.tsdblite.json;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.buffer.Unpooled;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.management.ObjectName;
import javax.management.openmbean.TabularData;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.heliosapm.tsdblite.metric.Trace;
import com.heliosapm.tsdblite.metric.Trace.TraceArrayDeserializer;
import com.heliosapm.tsdblite.metric.Trace.TraceDeserializer;
import com.heliosapm.tsdblite.metric.Trace.TraceSerializer;
import com.heliosapm.utils.jmx.JMXHelper;

/**
 * <p>Title: JSON</p>
 * <p>Description: JSON Utilities</p> 
 * <p>Company: Helios Development Group LLC</p>
 * @author Whitehead (nwhitehead AT heliosdev DOT org)
 * <p><code>com.heliosapm.tsdblite.json.JSON</code></p>
 */

public class JSON {
    public static final Charset UTF8 = Charset.forName("UTF8");
    private static final ObjectMapper jsonMapper = new ObjectMapper();
    private static final Map<String, String> EMPTY_MAP = Collections.emptyMap();
    static {
        jsonMapper.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
        registerSerializer(Trace.class, new TraceSerializer());
        registerDeserializer(Trace.class, new TraceDeserializer());

        registerDeserializer(Trace.class, new TraceDeserializer());
        registerDeserializer(Trace[].class, new TraceArrayDeserializer());
    }

    public static Map<String, String> from(final JsonNode node) {
        if (node == null)
            return EMPTY_MAP;
        final int size = node.size();
        if (size == 0)
            return EMPTY_MAP;
        final Map<String, String> map = new HashMap<String, String>(node.size());
        for (Iterator<String> iter = node.fieldNames(); iter.hasNext();) {
            final String key = iter.next();
            final JsonNode v = node.get(key);
            if (v.isTextual()) {
                map.put(key, v.textValue());
            }
        }
        return map;
    }

    /**
     * Registers a deser for the passed class
     * @param clazz The class for which a deser is being registered
     * @param deser The deserializer
     */
    public static <T> void registerDeserializer(final Class<T> clazz, final JsonDeserializer<T> deser) {
        if (clazz == null)
            throw new IllegalArgumentException("The passed class was null");
        if (deser == null)
            throw new IllegalArgumentException("The passed deserializer for [" + clazz.getName() + "] was null");
        final SimpleModule module = new SimpleModule();
        module.addDeserializer(clazz, deser);
        jsonMapper.registerModule(module);
    }

    /**
     * Registers a ser for the passed class
     * @param clazz The class for which a ser is being registered
     * @param ser The serializer
     */
    public static <T> void registerSerializer(final Class<T> clazz, final JsonSerializer<T> ser) {
        if (clazz == null)
            throw new IllegalArgumentException("The passed class was null");
        if (ser == null)
            throw new IllegalArgumentException("The passed serializer for [" + clazz.getName() + "] was null");
        final SimpleModule module = new SimpleModule();
        module.addSerializer(clazz, ser);
        jsonMapper.registerModule(module);
    }

    /**
     * Registers a ser/deser pair for the passed class
     * @param clazz The class for which a ser/deser pair is being registered
     * @param deser The deserializer
     * @param ser The serializer
     */
    public static <T> void registerSerialization(final Class<T> clazz, final JsonDeserializer<T> deser,
            final JsonSerializer<T> ser) {
        if (clazz == null)
            throw new IllegalArgumentException("The passed class was null");
        if (ser == null)
            throw new IllegalArgumentException("The passed serializer for [" + clazz.getName() + "] was null");
        if (deser == null)
            throw new IllegalArgumentException("The passed deserializer for [" + clazz.getName() + "] was null");
        final SimpleModule module = new SimpleModule();
        int added = 0;
        module.addSerializer(clazz, ser);
        module.addDeserializer(clazz, deser);
        if (added > 0)
            jsonMapper.registerModule(module);
    }

    /**
     * Registers a module with the shared json mapper
     * @param module The module to register
     */
    public static void registerModule(final Module module) {
        if (module == null)
            throw new IllegalArgumentException("The passed module was null");
        jsonMapper.registerModule(module);
    }

    /**
     * Deserializes a JSON formatted string to a specific class type
     * <b>Note:</b> If you get mapping exceptions you may need to provide a 
     * TypeReference
     * @param json The string to deserialize
     * @param pojo The class type of the object used for deserialization
     * @return An object of the {@code pojo} type
     * @throws IllegalArgumentException if the data or class was null or parsing 
     * failed
     * @throws JSONException if the data could not be parsed
     */
    public static final <T> T parseToObject(final String json, final Class<T> pojo) {
        if (json == null || json.isEmpty())
            throw new IllegalArgumentException("Incoming data was null or empty");
        if (pojo == null)
            throw new IllegalArgumentException("Missing class type");

        try {
            return jsonMapper.readValue(json, pojo);
        } catch (JsonParseException e) {
            throw new IllegalArgumentException(e);
        } catch (JsonMappingException e) {
            throw new IllegalArgumentException(e);
        } catch (IOException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Deserializes a JSON/UTF8 formatted byte array to a specific class type
     * <b>Note:</b> If you get mapping exceptions you may need to provide a 
     * TypeReference
     * @param json The buffer to deserialize from
     * @param pojo The class type of the object used for deserialization
     * @return An object of the {@code pojo} type
     * @throws IllegalArgumentException if the data or class was null or parsing 
     * failed
     * @throws JSONException if the data could not be parsed
     */
    public static final <T> T parseToObject(final ByteBuf json, final Class<T> pojo) {
        return parseToObject(json, pojo, UTF8);
    }

    /**
     * Deserializes a JSON formatted byte array to a specific class type
     * <b>Note:</b> If you get mapping exceptions you may need to provide a 
     * TypeReference
     * @param json The buffer to deserialize from
     * @param pojo The class type of the object used for deserialization
     * @param charset The character set of the content type in the buffer
     * @return An object of the {@code pojo} type
     * @throws IllegalArgumentException if the data or class was null or parsing 
     * failed
     * @throws JSONException if the data could not be parsed
     */
    public static final <T> T parseToObject(final ByteBuf json, final Class<T> pojo, final Charset charset) {
        if (json == null)
            throw new IllegalArgumentException("Incoming buffer was null");
        if (pojo == null)
            throw new IllegalArgumentException("Missing class type");
        if (charset == null)
            throw new IllegalArgumentException("Missing charset");
        InputStream is = new ByteBufInputStream(json);
        InputStreamReader isr = new InputStreamReader(is, charset);
        try {
            return jsonMapper.readValue(isr, pojo);
        } catch (JsonParseException e) {
            throw new IllegalArgumentException(e);
        } catch (JsonMappingException e) {
            throw new IllegalArgumentException(e);
        } catch (IOException e) {
            throw new JSONException(e);
        } finally {
            if (is != null)
                try {
                    is.close();
                } catch (Exception x) {
                    /* No Op */}
            if (isr != null)
                try {
                    isr.close();
                } catch (Exception x) {
                    /* No Op */}
        }
    }

    /**
     * Deserializes a JSON formatted ByteBuf to a JsonNode
     * @param json The buffer to deserialize from
     * @param charset The optional character set of the content type in the buffer which defaults to UTF8
     * @return The parsed JsonNode
     * @throws IllegalArgumentException if buffer was null
     * @throws JSONException if the data could not be parsed
     */
    public static final JsonNode parseToNode(final ByteBuf json, final Charset charset) {
        if (json == null)
            throw new IllegalArgumentException("Incoming buffer was null");
        InputStream is = new ByteBufInputStream(json);
        InputStreamReader isr = new InputStreamReader(is, charset == null ? UTF8 : charset);
        try {
            return jsonMapper.readTree(is);
        } catch (JsonParseException e) {
            throw new IllegalArgumentException(e);
        } catch (JsonMappingException e) {
            throw new IllegalArgumentException(e);
        } catch (IOException e) {
            throw new JSONException(e);
        } finally {
            if (is != null)
                try {
                    is.close();
                } catch (Exception x) {
                    /* No Op */}
            if (isr != null)
                try {
                    isr.close();
                } catch (Exception x) {
                    /* No Op */}
        }
    }

    /**
     * Deserializes a JSON formatted ByteBuf to a JsonNode
     * @param json The buffer to deserialize from which is assumed to be UTF8
     * @return The parsed JsonNode
     * @throws IllegalArgumentException if buffer was null
     * @throws JSONException if the data could not be parsed
     */
    public static final JsonNode parseToNode(final ByteBuf json) {
        return parseToNode(json, UTF8);
    }

    /**
     * Deserializes a JSON node to a specific class type
     * <b>Note:</b> If you get mapping exceptions you may need to provide a 
     * TypeReference
     * @param json The node to deserialize
     * @param pojo The class type of the object used for deserialization
     * @return An object of the {@code pojo} type
     * @throws IllegalArgumentException if the data or class was null or parsing 
     * failed
     * @throws JSONException if the data could not be parsed
     */
    public static final <T> T parseToObject(final JsonNode json, final Class<T> pojo) {
        if (json == null)
            throw new IllegalArgumentException("Incoming data was null or empty");
        if (pojo == null)
            throw new IllegalArgumentException("Missing class type");
        return jsonMapper.convertValue(json, pojo);
    }

    /**
     * Parses the passed stringy and returns the resulting JsonNode
     * @param cs the stringy to parse
     * @return the JsonNode
     */
    public static JsonNode parse(final CharSequence cs) {
        if (cs == null)
            throw new IllegalArgumentException("The passed CharSequence was null or empty");
        try {
            return jsonMapper.readTree(cs.toString().trim());
        } catch (Exception ex) {
            throw new JSONException(ex);
        }
    }

    /**
     * Returns a json generator that writes to the passed output stream
     * @param os The output sream to write to
     * @return the generator
     */
    public static JsonGenerator generatorFor(final OutputStream os) {
        if (os == null)
            throw new IllegalArgumentException("The passed OutputStream was null");
        try {
            return getFactory().createGenerator(os);
        } catch (IOException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Deserializes a JSON formatted byte array to a specific class type
     * <b>Note:</b> If you get mapping exceptions you may need to provide a 
     * TypeReference
     * @param json The byte array to deserialize
     * @param pojo The class type of the object used for deserialization
     * @return An object of the {@code pojo} type
     * @throws IllegalArgumentException if the data or class was null or parsing 
     * failed
     * @throws JSONException if the data could not be parsed
     */
    public static final <T> T parseToObject(final byte[] json, final Class<T> pojo) {
        if (json == null)
            throw new IllegalArgumentException("Incoming data was null");
        if (pojo == null)
            throw new IllegalArgumentException("Missing class type");
        try {
            return jsonMapper.readValue(json, pojo);
        } catch (JsonParseException e) {
            throw new IllegalArgumentException(e);
        } catch (JsonMappingException e) {
            throw new IllegalArgumentException(e);
        } catch (IOException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Deserializes a JSON formatted string to a specific class type
     * @param json The string to deserialize
     * @param type A type definition for a complex object
     * @return An object of the {@code pojo} type
     * @throws IllegalArgumentException if the data or type was null or parsing
     * failed
     * @throws JSONException if the data could not be parsed
     */
    @SuppressWarnings("unchecked")
    public static final <T> T parseToObject(final String json, final TypeReference<T> type) {
        if (json == null || json.isEmpty())
            throw new IllegalArgumentException("Incoming data was null or empty");
        if (type == null)
            throw new IllegalArgumentException("Missing type reference");
        try {
            return (T) jsonMapper.readValue(json, type);
        } catch (JsonParseException e) {
            throw new IllegalArgumentException(e);
        } catch (JsonMappingException e) {
            throw new IllegalArgumentException(e);
        } catch (IOException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Deserializes a JSON formatted byte array to a specific class type
     * @param json The byte array to deserialize
     * @param type A type definition for a complex object
     * @return An object of the {@code pojo} type
     * @throws IllegalArgumentException if the data or type was null or parsing
     * failed
     * @throws JSONException if the data could not be parsed
     */
    @SuppressWarnings("unchecked")
    public static final <T> T parseToObject(final byte[] json, final TypeReference<T> type) {
        if (json == null)
            throw new IllegalArgumentException("Incoming data was null");
        if (type == null)
            throw new IllegalArgumentException("Missing type reference");
        try {
            return (T) jsonMapper.readValue(json, type);
        } catch (JsonParseException e) {
            throw new IllegalArgumentException(e);
        } catch (JsonMappingException e) {
            throw new IllegalArgumentException(e);
        } catch (IOException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Parses a JSON formatted string into raw tokens for streaming or tree
     * iteration
     * <b>Warning:</b> This method can parse an invalid JSON object without
     * throwing an error until you start processing the data
     * @param json The string to parse
     * @return A JsonParser object to be used for iteration
     * @throws IllegalArgumentException if the data was null or parsing failed
     * @throws JSONException if the data could not be parsed
     */
    public static final JsonParser parseToStream(final String json) {
        if (json == null || json.isEmpty())
            throw new IllegalArgumentException("Incoming data was null or empty");
        try {
            return jsonMapper.getFactory().createParser(json);
        } catch (JsonParseException e) {
            throw new IllegalArgumentException(e);
        } catch (IOException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Parses the passed stringy into a JsonNode
     * @param jsonStr The stringy to parse
     * @return the parsed JsonNode
     */
    public static JsonNode parseToNode(final CharSequence jsonStr) {
        if (jsonStr == null)
            throw new IllegalArgumentException("Incoming data was null");
        final String str = jsonStr.toString().trim();
        if (str.isEmpty())
            throw new IllegalArgumentException("Incoming data was empty");
        try {
            return jsonMapper.readTree(str);
        } catch (JsonParseException e) {
            throw new IllegalArgumentException(e);
        } catch (IOException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Parses a JSON formatted byte array into raw tokens for streaming or tree
     * iteration
     * <b>Warning:</b> This method can parse an invalid JSON object without
     * throwing an error until you start processing the data
     * @param json The byte array to parse
     * @return A JsonParser object to be used for iteration
     * @throws IllegalArgumentException if the data was null or parsing failed
     * @throws JSONException if the data could not be parsed
     */
    public static final JsonParser parseToStream(final byte[] json) {
        if (json == null)
            throw new IllegalArgumentException("Incoming data was null");
        try {
            return jsonMapper.getFactory().createParser(json);
        } catch (JsonParseException e) {
            throw new IllegalArgumentException(e);
        } catch (IOException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Parses a JSON formatted inputs stream into raw tokens for streaming or tree
     * iteration
     * <b>Warning:</b> This method can parse an invalid JSON object without
     * throwing an error until you start processing the data
     * @param json The input stream to parse
     * @return A JsonParser object to be used for iteration
     * @throws IllegalArgumentException if the data was null or parsing failed
     * @throws JSONException if the data could not be parsed
     */
    public static final JsonParser parseToStream(final InputStream json) {
        if (json == null)
            throw new IllegalArgumentException("Incoming data was null");
        try {
            return jsonMapper.getFactory().createParser(json);
        } catch (JsonParseException e) {
            throw new IllegalArgumentException(e);
        } catch (IOException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Serializes the given object to a JSON string
     * @param object The object to serialize
     * @return A JSON formatted string
     * @throws IllegalArgumentException if the object was null
     * @throws JSONException if the object could not be serialized
     */
    public static final String serializeToString(final Object object) {
        if (object == null)
            throw new IllegalArgumentException("Object was null");
        try {
            return jsonMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Converts the passed object to a JsonNode
     * @param object The object to convert
     * @return the resulting JsonNode
     */
    public static final JsonNode serializeToNode(final Object object) {
        if (object == null)
            throw new IllegalArgumentException("Object was null");
        return jsonMapper.convertValue(object, JsonNode.class);
    }

    /**
     * Serializes the given object to a JSON byte array
     * @param object The object to serialize
     * @return A JSON formatted byte array
     * @throws IllegalArgumentException if the object was null
     * @throws JSONException if the object could not be serialized
     */
    public static final byte[] serializeToBytes(final Object object) {
        if (object == null)
            throw new IllegalArgumentException("Object was null");
        try {
            return jsonMapper.writeValueAsBytes(object);
        } catch (JsonProcessingException e) {
            throw new JSONException(e);
        }
    }

    public static void serialize(final Object object, final OutputStream os) {
        if (object == null)
            throw new IllegalArgumentException("Object was null");
        if (os == null)
            throw new IllegalArgumentException("OutputStream was null");
        try {
            jsonMapper.writeValue(os, object);
            os.flush();
        } catch (Exception ex) {
            throw new JSONException(ex);
        }
    }

    /**
     * Serializes the passed object as JSON into the passed buffer
     * @param obj The object to serialize
     * @param buf The buffer to serialize into. If null, a new buffer is created
     * @return The buffer the object was written to
     */
    public static ByteBuf serializeToBuf(final Object obj, final ByteBuf buf) {
        if (obj == null)
            throw new IllegalArgumentException("The passed object was null");
        final ByteBuf b = buf == null ? Unpooled.directBuffer(2048) : buf;
        OutputStream os = null;
        try {
            os = new ByteBufOutputStream(b);
            serialize(obj, os);
            os.flush();
            return b;
        } catch (Exception ex) {
            throw new RuntimeException("Failed to bufferize serialized object", ex);
        } finally {
            if (os != null)
                try {
                    os.close();
                } catch (Exception x) {
                    /* No Op */}
        }
    }

    /**
     * Serializes the passed object as JSON into a newly created buffer
     * @param obj The object to serialize
     * @return The buffer the object was written to
     */
    public static ByteBuf serializeToBuf(final Object obj) {
        return serializeToBuf(obj, null);
    }

    /**
     * Serializes the passed object and pipes back the results in an InputStream to read it back.
     * Spawns a thread to run the pipe out so the calling thread only needs to read the returned input stream.
     * If the serialization fails, the worker thread will close the inoput stream to signal the failure.
     * @param obj The object to serialize
     * @return an InputStream to read back the JSON serialized object 
     */
    public static InputStream serializeLoopBack(final Object obj) {
        if (obj == null)
            throw new IllegalArgumentException("The passed object was null");
        try {
            final PipedInputStream pin = new PipedInputStream(2048);
            final PipedOutputStream pout = new PipedOutputStream(pin);
            final Thread t = new Thread("serializeLoopBackThread") {
                @Override
                public void run() {
                    try {
                        serialize(obj, pout);
                    } catch (Exception ex) {
                        try {
                            pin.close();
                        } catch (Exception x) {
                            /* No Op */}
                    }
                }
            };
            t.setDaemon(true);
            t.start();
            return pin;
        } catch (Exception ex) {
            throw new RuntimeException("Failed to pipe serialized object", ex);
        }
    }

    /**
     * Serializes the given object and wraps it in a callback function
     * i.e. &lt;callback&gt;(&lt;json&gt)
     * Note: This will not append a trailing semicolon
     * @param callback The name of the Javascript callback to prepend
     * @param object The object to serialize
     * @return A JSONP formatted string
     * @throws IllegalArgumentException if the callback method name was missing 
     * or object was null
     * @throws JSONException if the object could not be serialized
     */
    public static final String serializeToJSONPString(final String callback, final Object object) {
        if (callback == null || callback.isEmpty())
            throw new IllegalArgumentException("Missing callback name");
        if (object == null)
            throw new IllegalArgumentException("Object was null");
        try {
            return jsonMapper.writeValueAsString(new JSONPObject(callback, object));
        } catch (JsonProcessingException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Serializes the given object and wraps it in a callback function
     * i.e. &lt;callback&gt;(&lt;json&gt)
     * Note: This will not append a trailing semicolon
     * @param callback The name of the Javascript callback to prepend
     * @param object The object to serialize
     * @return A JSONP formatted byte array
     * @throws IllegalArgumentException if the callback method name was missing 
     * or object was null
     * @throws JSONException if the object could not be serialized
     * @throws IOException Thrown when there was an issue reading the object
     */
    public static final byte[] serializeToJSONPBytes(final String callback, final Object object) {
        if (callback == null || callback.isEmpty())
            throw new IllegalArgumentException("Missing callback name");
        if (object == null)
            throw new IllegalArgumentException("Object was null");
        try {
            return jsonMapper.writeValueAsBytes(new JSONPObject(callback, object));
        } catch (JsonProcessingException e) {
            throw new JSONException(e);
        }
    }

    /**
     * Returns a reference to the static ObjectMapper
     * @return The ObjectMapper
     */
    public final static ObjectMapper getMapper() {
        return jsonMapper;
    }

    /**
     * Returns a reference to the JsonFactory for streaming creation
     * @return The JsonFactory object
     */
    public final static JsonFactory getFactory() {
        return jsonMapper.getFactory();
    }

    /**
     * Returns a shareable node factory
     * @return a json node factory
     */
    public static JsonNodeFactory getNodeFactory() {
        return JsonNodeFactory.instance;
    }

    /**
     * <p>Title: ObjectNameSerializer</p>
     * <p>Description: Built in JSON serializer for {@link ObjectName}s</p> 
     * <p>Company: Helios Development Group LLC</p>
     * @author Whitehead (nwhitehead AT heliosdev DOT org)
     * <p><code>org.helios.nash.util.JSON.ObjectNameSerializer</code></p>
     */
    public static class ObjectNameSerializer extends JsonSerializer<ObjectName> {
        @Override
        public void serialize(final ObjectName value, final JsonGenerator jgen, final SerializerProvider provider)
                throws IOException, JsonProcessingException {
            if (value == null) {
                jgen.writeNull();
            } else {
                jgen.writeString(value.toString());
            }
        }
    }

    /**
     * <p>Title: ObjectNameDeserializer</p>
     * <p>Description: Built in JSON deserializer for {@link ObjectName}s</p> 
     * <p>Company: Helios Development Group LLC</p>
     * @author Whitehead (nwhitehead AT heliosdev DOT org)
     * <p><code>org.helios.nash.util.JSON.ObjectNameDeserializer</code></p>
     */
    public static class ObjectNameDeserializer extends JsonDeserializer<ObjectName> {

        @Override
        public ObjectName deserialize(final JsonParser jp, final DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            final String s = jp.getText();
            return (s == null || s.trim().isEmpty()) ? null : JMXHelper.objectName(s.trim());
        }

    }

    /**
     * <p>Title: TabularDataSerializer</p>
     * <p>Description: Built in JSON serializer for {@link TabularData}s</p> 
     * <p>Company: Helios Development Group LLC</p>
     * @author Whitehead (nwhitehead AT heliosdev DOT org)
     * <p><code>org.helios.nash.util.JSON.TabularDataSerializer</code></p>
     */
    public static class TabularDataSerializer extends JsonSerializer<TabularData> {
        @Override
        public void serialize(final TabularData value, final JsonGenerator jgen, final SerializerProvider provider)
                throws IOException, JsonProcessingException {
            if (value == null) {
                jgen.writeNull();
            } else {
                jgen.writeBinary(jserialize((Serializable) value));

                //jgen.writeString(value.toString());
            }
        }
    }

    /**
     * <p>Title: TabularDataDeserializer</p>
     * <p>Description: Built in JSON deserializer for {@link TabularData}s</p> 
     * <p>Company: Helios Development Group LLC</p>
     * @author Whitehead (nwhitehead AT heliosdev DOT org)
     * <p><code>org.helios.nash.util.JSON.TabularDataDeserializer</code></p>
     */
    public static class TabularDataDeserializer extends JsonDeserializer<TabularData> {

        @Override
        public TabularData deserialize(JsonParser jp, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            return null;
        }

    }

    private JSON() {
    }

    private static byte[] jserialize(final Serializable ser) {
        if (ser == null)
            return new byte[0];
        ByteArrayOutputStream baos = null;
        ObjectOutputStream oos = null;
        try {
            baos = new ByteArrayOutputStream(1024);
            oos = new ObjectOutputStream(baos);
            oos.writeObject(ser);
            oos.flush();
            baos.flush();
            return baos.toByteArray();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        } finally {
            if (oos != null)
                try {
                    oos.close();
                } catch (Exception x) {
                    /* No Op */}
            if (baos != null)
                try {
                    baos.close();
                } catch (Exception x) {
                    /* No Op */}
        }
    }

    private static Object jdeserialize(final byte[] bytes) {
        if (bytes == null || bytes.length == 0)
            return null;
        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        try {
            bais = new ByteArrayInputStream(bytes);
            ois = new ObjectInputStream(bais);
            return ois.readObject();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        } finally {
            if (ois != null)
                try {
                    ois.close();
                } catch (Exception x) {
                    /* No Op */}
            if (bais != null)
                try {
                    bais.close();
                } catch (Exception x) {
                    /* No Op */}
        }
    }

}