commting AXIS2C-1645 patch

diff --git a/configure.ac b/configure.ac
index 0d0a308..dd2f3d0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -496,6 +496,29 @@
   CPPFLAGS="$CPPFLAGS"
 )
 
+AC_MSG_CHECKING(whether to use JSON)
+AC_ARG_ENABLE(json, [  --enable-json  
+                          enable json support (default=no)],
+[ case "${enableval}" in
+  no)
+    AC_MSG_RESULT(no)
+    CFLAGS="$CFLAGS"
+    CPPFLAGS="$CPPFLAGS"
+    json_enabled=false
+    ;;
+  *)
+    AC_MSG_RESULT(yes)
+    CFLAGS="$CFLAGS $JSON_CFLAGS -DAXIS2_JSON_ENABLED"
+    CPPFLAGS="$CPPFLAGS $JSON_LIBS -DAXIS2_JSON_ENABLED"
+    json_enabled=true
+    PKG_CHECK_MODULES(JSON, json)
+    ;;
+  esac ],
+  AC_MSG_RESULT(no)
+  CFLAGS="$CFLAGS"
+  CPPFLAGS="$CPPFLAGS"
+)
+
 
 APACHE2INC=$apache2inc
 OPENSSLINC=$opensslinc
@@ -529,6 +552,7 @@
 AC_SUBST(ZLIBBUILD)
 AM_CONDITIONAL(AXIS2_SSL_ENABLED, test x$ssl_enabled = xtrue)
 AM_CONDITIONAL(AXIS2_LIBCURL_ENABLED, test x$libcurl_enabled = xtrue)
+AM_CONDITIONAL(AXIS2_JSON_ENABLED, test x$json_enabled = xtrue)
 
 export NTLM_LDFLAGS
 export WRAPPER_DIR
diff --git a/include/axis2_http_transport.h b/include/axis2_http_transport.h
index 7bf5c53..f39b7d4 100644
--- a/include/axis2_http_transport.h
+++ b/include/axis2_http_transport.h
@@ -742,6 +742,13 @@
      */
     #define AXIS2_HTTP_HEADER_ACCEPT_MULTIPART_RELATED AXIOM_MIME_TYPE_MULTIPART_RELATED
 
+#ifdef AXIS2_JSON_ENABLED
+    /**
+     * AXIS2_HTTP_HEADER_ACCEPT_JSON
+     */
+#define AXIS2_HTTP_HEADER_ACCEPT_JSON "application/json"
+#endif
+
     /**
      * HEADER_ACCEPT_APPLICATION_DIME
      */
diff --git a/include/axis2_json_reader.h b/include/axis2_json_reader.h
new file mode 100644
index 0000000..cd8ff04
--- /dev/null
+++ b/include/axis2_json_reader.h
@@ -0,0 +1,186 @@
+/*
+ *  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.
+ */
+
+#ifndef AXIS2_JSON_READER_H
+#define AXIS2_JSON_READER_H
+
+#include <axutil_utils.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct axutil_stream axutil_stream_t;
+typedef struct axiom_node axiom_node_t;
+typedef struct axutil_env axutil_env_t;
+typedef struct axis2_json_reader axis2_json_reader_t;
+
+/**
+ * @brief Creates JSON reader to read data from stream
+ * @param env Environment
+ * @param stream Stream to read data from
+ */
+AXIS2_EXTERN axis2_json_reader_t* AXIS2_CALL
+axis2_json_reader_create_for_stream(
+        const axutil_env_t* env,
+        axutil_stream_t* stream);
+
+
+/**
+ * @brief Creates JSON reader to read data from string
+ * @param env Environment
+ * @param json_string JSON string
+ * @param json_string_size JSON string
+ */
+AXIS2_EXTERN axis2_json_reader_t* AXIS2_CALL
+axis2_json_reader_create_for_memory(
+        const axutil_env_t* env,
+        const axis2_char_t* json_string,
+        int json_string_size);
+
+
+/**
+ * @brief Destroys reader
+ *  does not free root node.
+ *  user must free axiom tree using axiom_node_free_tree()
+ * @param reader JSON reader
+ * @param env Environment
+ */
+AXIS2_EXTERN void AXIS2_CALL
+axis2_json_reader_free(
+        axis2_json_reader_t* reader,
+        const axutil_env_t* env);
+
+
+/**
+ * @brief Starts reading from string or stream
+ * @param reader JSON reader
+ * @param env Environment
+ */
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axis2_json_reader_read(
+        axis2_json_reader_t* reader,
+        const axutil_env_t* env);
+
+
+/**
+ * @brief Gets root node of parsed data
+ * @param reader JSON reader
+ * @param env Environment
+ */
+AXIS2_EXTERN axiom_node_t* AXIS2_CALL
+axis2_json_reader_get_root_node(
+        axis2_json_reader_t* reader,
+        const axutil_env_t* env);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/*
+ *  Copyright 2013 Utkin Dmitry
+ *
+ *  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.
+ */
+
+#ifndef AXIS2_JSON_READER_H
+#define AXIS2_JSON_READER_H
+
+#include <axutil_utils_defines.h>
+#include <axutil_stream.h>
+#include <axiom_node.h>
+#include <axutil_env.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct axis2_json_reader axis2_json_reader_t;
+
+/**
+ * @brief Creates JSON reader to read data from stream
+ * @param env Environment
+ * @param stream Stream to read data from
+ */
+AXIS2_EXTERN axis2_json_reader_t* AXIS2_CALL
+axis2_json_reader_create_for_stream(
+        const axutil_env_t* env,
+        axutil_stream_t* stream);
+
+
+/**
+ * @brief Creates JSON reader to read data from string
+ * @param env Environment
+ * @param json_string JSON string
+ * @param json_string_size JSON string
+ */
+AXIS2_EXTERN axis2_json_reader_t* AXIS2_CALL
+axis2_json_reader_create_for_memory(
+        const axutil_env_t* env,
+        const axis2_char_t* json_string,
+        int json_string_size);
+
+
+/**
+ * @brief Destroys reader
+ *  does not free root node.
+ *  user must free axiom tree using axiom_node_free_tree()
+ * @param reader JSON reader
+ * @param env Environment
+ */
+AXIS2_EXTERN void AXIS2_CALL
+axis2_json_reader_free(
+        axis2_json_reader_t* reader,
+        const axutil_env_t* env);
+
+
+/**
+ * @brief Starts reading from string or stream
+ * @param reader JSON reader
+ * @param env Environment
+ */
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axis2_json_reader_read(
+        axis2_json_reader_t* reader,
+        const axutil_env_t* env);
+
+
+/**
+ * @brief Gets root node of parsed data
+ * @param reader JSON reader
+ * @param env Environment
+ */
+AXIS2_EXTERN axiom_node_t* AXIS2_CALL
+axis2_json_reader_get_root_node(
+        axis2_json_reader_t* reader,
+        const axutil_env_t* env);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/axis2_json_writer.h b/include/axis2_json_writer.h
new file mode 100644
index 0000000..729bba4
--- /dev/null
+++ b/include/axis2_json_writer.h
@@ -0,0 +1,156 @@
+/*
+ *  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.
+ */
+
+#ifndef AXIS2_JSON_WRITER_H
+#define AXIS2_JSON_WRITER_H
+
+#include <axutil_utils.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct axiom_node axiom_node_t;
+typedef struct axutil_env axutil_env_t;
+typedef struct axis2_json_writer axis2_json_writer_t;
+
+/**
+ * @brief Creates JSON writer
+ * @param env Environment
+ */
+AXIS2_EXTERN axis2_json_writer_t* AXIS2_CALL
+axis2_json_writer_create(
+        const axutil_env_t* env);
+
+
+/**
+ * @brief Destroys writer
+ * @param writer JSON writer
+ * @param env Environment
+ */
+AXIS2_EXTERN void AXIS2_CALL
+axis2_json_writer_free(
+        axis2_json_writer_t* writer,
+        const axutil_env_t* env);
+
+
+/**
+ * @brief Starts writing to JSON
+ * @param writer JSON writer
+ * @param node Source OM node
+ * @param env Environment
+ */
+AXIS2_EXTERN void AXIS2_CALL
+axis2_json_writer_write(
+        axis2_json_writer_t* writer,
+        const axiom_node_t* node,
+        const axutil_env_t* env);
+
+
+/**
+ * @brief Gets resulting JSON string
+ * @param writer JSON writer
+ * @param env Environment
+ */
+AXIS2_EXTERN const axis2_char_t* AXIS2_CALL
+axis2_json_writer_get_json_string(
+        axis2_json_writer_t* writer,
+        const axutil_env_t* env,
+        int* json_string_length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/*
+ *  Copyright 2013 Utkin Dmitry
+ *
+ *  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.
+ */
+
+#ifndef AXIS2_JSON_WRITER_H
+#define AXIS2_JSON_WRITER_H
+
+#include <axutil_utils_defines.h>
+#include <axiom_node.h>
+#include <axutil_env.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct axis2_json_writer axis2_json_writer_t;
+
+/**
+ * @brief Creates JSON writer
+ * @param env Environment
+ */
+AXIS2_EXTERN axis2_json_writer_t* AXIS2_CALL
+axis2_json_writer_create(
+        const axutil_env_t* env);
+
+
+/**
+ * @brief Destroys writer
+ * @param writer JSON writer
+ * @param env Environment
+ */
+AXIS2_EXTERN void AXIS2_CALL
+axis2_json_writer_free(
+        axis2_json_writer_t* writer,
+        const axutil_env_t* env);
+
+
+/**
+ * @brief Starts writing to JSON
+ * @param writer JSON writer
+ * @param node Source OM node
+ * @param env Environment
+ */
+AXIS2_EXTERN void AXIS2_CALL
+axis2_json_writer_write(
+        axis2_json_writer_t* writer,
+        const axiom_node_t* node,
+        const axutil_env_t* env);
+
+
+/**
+ * @brief Gets resulting JSON string
+ * @param writer JSON writer
+ * @param env Environment
+ */
+AXIS2_EXTERN const axis2_char_t* AXIS2_CALL
+axis2_json_writer_get_json_string(
+        axis2_json_writer_t* writer,
+        const axutil_env_t* env,
+        int* json_string_length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/axis2_msg_ctx.h b/include/axis2_msg_ctx.h
index b1d4d0f..e1b7395 100644
--- a/include/axis2_msg_ctx.h
+++ b/include/axis2_msg_ctx.h
@@ -2088,6 +2088,17 @@
         const axutil_env_t * env);
 
 
+#ifdef AXIS2_JSON_ENABLED
+    AXIS2_EXTERN axis2_bool_t AXIS2_CALL
+    axis2_msg_ctx_get_doing_json(
+        const axis2_msg_ctx_t *msg_ctx,
+        const axutil_env_t *env);
+
+    AXIS2_EXTERN axis2_status_t AXIS2_CALL
+    axis2_msg_ctx_set_doing_json(axis2_msg_ctx_t *msg_ctx,
+        const axutil_env_t *env,
+        const axis2_bool_t doing_json);
+#endif
 
 /** @} */
 
diff --git a/src/core/context/msg_ctx.c b/src/core/context/msg_ctx.c
index 7a1523e..f4c4a40 100644
--- a/src/core/context/msg_ctx.c
+++ b/src/core/context/msg_ctx.c
@@ -127,6 +127,11 @@
     /** Rest through HTTP POST? */
     axis2_bool_t do_rest_through_post;
 
+#ifdef AXIS2_JSON_ENABLED
+    /** are we doing json now? */
+    axis2_bool_t doing_json;
+#endif
+
     /** Session management enabled? */
     axis2_bool_t manage_session;
 
@@ -2823,3 +2828,22 @@
     }
     msg_ctx->mime_parts = mime_parts;
 }
+
+#ifdef AXIS2_JSON_ENABLED
+axis2_bool_t AXIS2_CALL
+axis2_msg_ctx_get_doing_json(
+    const axis2_msg_ctx_t *msg_ctx,
+    const axutil_env_t *env)
+{
+    return msg_ctx->doing_json;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+    axis2_msg_ctx_set_doing_json(axis2_msg_ctx_t *msg_ctx,
+        const axutil_env_t *env,
+        const axis2_bool_t doing_json)
+{
+    msg_ctx->doing_json = doing_json;
+    return AXIS2_SUCCESS;
+}
+#endif
diff --git a/src/core/engine/Makefile.am b/src/core/engine/Makefile.am
index 17eb157..ee935c7 100644
--- a/src/core/engine/Makefile.am
+++ b/src/core/engine/Makefile.am
@@ -59,3 +59,6 @@
 
 EXTRA_DIST=axis2_disp_checker.h
 
+if AXIS2_JSON_ENABLED
+libaxis2_engine_la_LIBADD += $(JSON_LIBS)
+endif
diff --git a/src/core/transport/http/sender/Makefile.am b/src/core/transport/http/sender/Makefile.am
index dd314d3..c0c0375 100644
--- a/src/core/transport/http/sender/Makefile.am
+++ b/src/core/transport/http/sender/Makefile.am
@@ -69,3 +69,10 @@
            -I$(top_builddir)/util/include \
            -I$(top_builddir)/axiom/include \
 		   $(SSL_INC)
+
+
+if AXIS2_JSON_ENABLED
+libaxis2_http_sender_la_SOURCES += axis2_json_writer.c
+libaxis2_http_sender_la_LIBADD += $(JSON_LIBS)
+INCLUDES += $(JSON_CFLAGS)
+endif
diff --git a/src/core/transport/http/sender/axis2_json_writer.c b/src/core/transport/http/sender/axis2_json_writer.c
new file mode 100644
index 0000000..e9001fe
--- /dev/null
+++ b/src/core/transport/http/sender/axis2_json_writer.c
@@ -0,0 +1,178 @@
+/*
+ *  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.
+ */
+
+#include <axiom_node.h>
+#include <axiom_element.h>
+#include <axiom_attribute.h>
+#include <json.h>
+#include "axis2_json_writer.h"
+
+#define AXIS2_JSON_XSI_URI "http://www.w3.org/2001/XMLSchema-instance"
+
+struct axis2_json_writer
+{
+    json_object* json_obj;
+};
+
+axis2_bool_t axis2_json_element_is_nil(axiom_element_t* om_element, const axutil_env_t* env)
+{
+    axiom_attribute_t* attr = NULL;
+    axutil_hash_index_t* index;
+    axutil_hash_t* attr_hash = axiom_element_get_all_attributes(om_element, env);
+
+    if (!attr_hash)
+        return AXIS2_FALSE;
+
+    for (index = axutil_hash_first(attr_hash, env);
+         index; index = axutil_hash_next(env, index))
+    {
+        axutil_hash_this(index, NULL, NULL, (void**)&attr);
+        if (attr && !strcmp(axiom_attribute_get_localname(attr, env), "nil"))
+        {
+            /* found some "nil" attribute, check it namespace */
+            axutil_qname_t* qname =
+                    axiom_attribute_get_qname(attr, env);
+            if (qname && !strcmp(axutil_qname_get_uri(qname, env), AXIS2_JSON_XSI_URI))
+            {
+                axis2_char_t* attr_value =
+                        axiom_attribute_get_value(attr, env);
+                return (!strcmp(attr_value, "true") || !strcmp(attr_value, "1")) ?
+                            AXIS2_TRUE : AXIS2_FALSE;
+            }
+        }
+    }
+
+    return AXIS2_FALSE;
+}
+
+void axis2_json_write_node(json_object* parent, axiom_node_t* om_node, const axutil_env_t* env)
+{
+    axiom_element_t* elem;
+    axiom_node_t* child_node;
+    const axis2_char_t* local_name;
+    json_object* obj;
+    json_object* array = NULL;
+
+    if (!om_node || axiom_node_get_node_type(om_node, env) != AXIOM_ELEMENT)
+        return;
+
+    elem = (axiom_element_t*)axiom_node_get_data_element(om_node, env);
+    local_name = axiom_element_get_localname(elem, env);
+
+    child_node = axiom_node_get_first_element(om_node, env);
+
+    /* find existing object */
+    if (json_object_object_get_ex(parent, local_name, &obj))
+    {
+        /* check that object is array? */
+        if (!json_object_is_type(obj, json_type_array))
+        {
+            /* convert to array */
+            obj = json_object_get(obj);
+            array = json_object_new_array();
+            json_object_array_add(array, obj);
+            json_object_object_del(parent, local_name);
+            json_object_object_add(parent, local_name, array);
+        }
+        else
+            array = obj;
+    }
+
+    if (!child_node)
+    {
+        /* this is a leaf node */
+        json_object* json_value = NULL;
+
+        /* check for nillable */
+        if (!axis2_json_element_is_nil(elem, env))
+        {
+            const axis2_char_t* value =
+                    axiom_element_get_text(elem, env, om_node);
+            json_value = json_object_new_string(value ? value : "");
+        }
+
+        if (array)
+            json_object_array_add(array, json_value);
+        else
+            json_object_object_add(parent, local_name, json_value);
+        return;
+    }
+
+    /* iterate through children elements */
+    obj = json_object_new_object();
+    if (array)
+        json_object_array_add(array, obj);
+    else
+        json_object_object_add(parent, local_name, obj);
+
+    for (; child_node; child_node = axiom_node_get_next_sibling(child_node, env))
+        if (axiom_node_get_node_type(child_node, env) == AXIOM_ELEMENT)
+            axis2_json_write_node(obj, child_node, env);
+}
+
+
+AXIS2_EXTERN axis2_json_writer_t* AXIS2_CALL
+axis2_json_writer_create(
+        const axutil_env_t* env)
+{
+    axis2_json_writer_t* writer = (axis2_json_writer_t*)AXIS2_MALLOC(env->allocator,
+                                                                     sizeof(struct axis2_json_writer));
+    if (writer)
+        writer->json_obj = NULL;
+
+    return writer;
+}
+
+
+AXIS2_EXTERN void AXIS2_CALL
+axis2_json_writer_free(
+        axis2_json_writer_t* writer,
+        const axutil_env_t* env)
+{
+    json_object_put(writer->json_obj);
+    AXIS2_FREE(env->allocator, writer);
+}
+
+
+AXIS2_EXTERN void AXIS2_CALL
+axis2_json_writer_write(
+        axis2_json_writer_t* writer,
+        const axiom_node_t* node,
+        const axutil_env_t* env)
+{
+    /* free existing object */
+    if (writer->json_obj)
+        json_object_put(writer->json_obj);
+
+    writer->json_obj = json_object_new_object();
+    axis2_json_write_node(writer->json_obj, (axiom_node_t*)node, env);
+}
+
+
+AXIS2_EXTERN const axis2_char_t* AXIS2_CALL
+axis2_json_writer_get_json_string(
+        axis2_json_writer_t* writer,
+        const axutil_env_t* env,
+        int* json_string_length)
+{
+    (void)env;
+    const axis2_char_t* result =
+            (const axis2_char_t*)json_object_to_json_string_ext(writer->json_obj,
+                                                               JSON_C_TO_STRING_PLAIN);
+    if (json_string_length)
+        *json_string_length = strlen(result);
+
+    return result;
+}
+
diff --git a/src/core/transport/http/sender/http_transport_sender.c b/src/core/transport/http/sender/http_transport_sender.c
index 6dc43fa..c4b954c 100644
--- a/src/core/transport/http/sender/http_transport_sender.c
+++ b/src/core/transport/http/sender/http_transport_sender.c
@@ -35,6 +35,10 @@
 #include "libcurl/axis2_libcurl.h"
 #endif
 
+#ifdef AXIS2_JSON_ENABLED
+#include <axis2_json_writer.h>
+#endif
+
 /**
  * HTTP Transport Sender struct impl
  * Axis2 HTTP Transport Sender impl
@@ -258,6 +262,89 @@
         return AXIS2_SUCCESS;
     }
 
+#ifdef AXIS2_JSON_ENABLED
+    if (AXIS2_TRUE == axis2_msg_ctx_get_doing_json(msg_ctx, env))
+    {
+        axis2_json_writer_t* json_writer;
+        axiom_node_t *body_node = NULL;
+        axiom_soap_body_t* soap_body =
+                axiom_soap_envelope_get_body(soap_data_out, env);
+        axutil_stream_t* out_stream =
+            axis2_msg_ctx_get_transport_out_stream(msg_ctx, env);
+
+        if (!soap_body)
+        {
+            AXIS2_ERROR_SET(env->error,
+                    AXIS2_ERROR_SOAP_ENVELOPE_OR_SOAP_BODY_NULL,
+                    AXIS2_FAILURE);
+            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "%s",
+                    AXIS2_ERROR_GET_MESSAGE(env->error));
+            return AXIS2_FAILURE;
+        }
+
+        body_node = axiom_soap_body_get_base_node(soap_body, env);
+        if (!body_node)
+        {
+            return AXIS2_FAILURE;
+        }
+
+        data_out = axiom_node_get_first_element(body_node, env);
+        if (!data_out || axiom_node_get_node_type(data_out, env)
+                != AXIOM_ELEMENT)
+        {
+            return AXIS2_FAILURE;
+        }
+
+        json_writer = axis2_json_writer_create(env);
+        if (!json_writer)
+        {
+            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+                            "Failed to create JSON writer");
+            return AXIS2_FAILURE;
+        }
+
+        axis2_json_writer_write(json_writer, data_out, env);
+
+        buffer = (axis2_char_t*)axis2_json_writer_get_json_string(
+                    json_writer, env, &buffer_size);
+        if (!buffer)
+        {
+            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+                            "Failed to get resulting JSON string");
+            return AXIS2_FAILURE;
+        }
+
+        if (AXIS2_TRUE == axis2_msg_ctx_get_server_side(msg_ctx, env))
+        {
+            axis2_op_ctx_t *op_ctx = NULL;
+            axis2_http_out_transport_info_t* out_info =
+                    (axis2_http_out_transport_info_t *)
+                    axis2_msg_ctx_get_out_transport_info(msg_ctx, env);
+
+            if (!out_info)
+            {
+                AXIS2_HANDLE_ERROR(env,
+                                   AXIS2_ERROR_OUT_TRNSPORT_INFO_NULL,
+                                   AXIS2_FAILURE);
+                return AXIS2_FAILURE;
+            }
+
+            AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_CHAR_ENCODING(
+                        out_info, env, char_set_enc);
+            AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_CONTENT_TYPE(
+                        out_info, env, AXIS2_HTTP_HEADER_ACCEPT_JSON);
+            op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env);
+            axis2_op_ctx_set_response_written(op_ctx, env, AXIS2_TRUE);
+        }
+
+        axutil_stream_write(out_stream, env, buffer, buffer_size);
+
+        axis2_json_writer_free(json_writer, env);
+
+        return AXIS2_SUCCESS;
+    }
+#endif
+
     xml_writer = axiom_xml_writer_create_for_memory(env, NULL, AXIS2_TRUE, 0,
         AXIS2_XML_PARSER_TYPE_BUFFER);
     if(!xml_writer)
diff --git a/src/core/transport/http/util/Makefile.am b/src/core/transport/http/util/Makefile.am
index c0411d4..2e0267b 100644
--- a/src/core/transport/http/util/Makefile.am
+++ b/src/core/transport/http/util/Makefile.am
@@ -26,3 +26,9 @@
             -I$(top_builddir)/src/core/engine \
             -I$(top_builddir)/util/include \
             -I$(top_builddir)/axiom/include
+
+if AXIS2_JSON_ENABLED
+libaxis2_http_util_la_SOURCES += axis2_json_reader.c
+libaxis2_http_util_la_LIBADD += $(JSON_LIBS)
+INCLUDES += $(JSON_CFLAGS)
+endif
diff --git a/src/core/transport/http/util/axis2_json_reader.c b/src/core/transport/http/util/axis2_json_reader.c
new file mode 100644
index 0000000..6cae42e
--- /dev/null
+++ b/src/core/transport/http/util/axis2_json_reader.c
@@ -0,0 +1,332 @@
+/*
+ *  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.
+ */
+
+#include <axutil_stream.h>
+#include <axiom_node.h>
+#include <axiom_element.h>
+#include <axiom_attribute.h>
+#include <json.h>
+#include "axis2_json_reader.h"
+
+#define AXIS2_JSON_XSI_URI "http://www.w3.org/2001/XMLSchema-instance"
+
+struct axis2_json_reader
+{
+    json_object* json_obj;
+    axiom_node_t* axiom_node;
+};
+
+const char* json_tokener_error_to_str(enum json_tokener_error error)
+{
+    switch (error)
+    {
+    case json_tokener_success:
+        return "success";
+    case json_tokener_continue:
+        return "continue";
+    case json_tokener_error_depth:
+        return "error_depth";
+    case json_tokener_error_parse_eof:
+        return "error_parse_eof";
+    case json_tokener_error_parse_unexpected:
+        return "error_parse_unexpected";
+    case json_tokener_error_parse_null:
+        return "error_parse_null";
+    case json_tokener_error_parse_boolean:
+        return "error_parse_boolean";
+    case json_tokener_error_parse_number:
+        return "error_parse_number";
+    case json_tokener_error_parse_array:
+        return "error_parse_array";
+    case json_tokener_error_parse_object_key_name:
+        return "error_parse_object_key_name";
+    case json_tokener_error_parse_object_key_sep:
+        return "error_parse_object_key_sep";
+    case json_tokener_error_parse_object_value_sep:
+        return "error_parse_object_value_sep";
+    case json_tokener_error_parse_string:
+        return "error_parse_string";
+    case json_tokener_error_parse_comment:
+        return "error_parse_comment";
+    }
+    return "UNKNOWN";
+}
+
+axis2_status_t
+axis2_json_read_node(
+        json_object* parent,
+        const char* name,
+        axiom_node_t** om_node,
+        const axutil_env_t* env);
+
+
+axis2_status_t
+axis2_json_read_child_node(
+        json_object* child_object,
+        const char* child_name,
+        axiom_node_t* om_node,
+        const axutil_env_t* env)
+{
+    axiom_node_t* child_node = NULL;
+
+    switch (json_object_get_type(child_object))
+    {
+    case json_type_object:
+    {
+        if (axis2_json_read_node(child_object, child_name, &child_node, env) != AXIS2_SUCCESS)
+            return AXIS2_FAILURE;
+        if (axiom_node_add_child(om_node, env, child_node) != AXIS2_SUCCESS)
+            return AXIS2_FAILURE;
+        break;
+    }
+
+    case json_type_array:
+    {
+        int i;
+        int array_len = json_object_array_length(child_object);
+        for (i = 0; i < array_len; ++i)
+        {
+            if (axis2_json_read_child_node(json_object_array_get_idx(child_object, i),
+                                       child_name, om_node, env) != AXIS2_SUCCESS)
+                return AXIS2_FAILURE;
+        }
+        break;
+    }
+
+    case json_type_int:
+    case json_type_boolean:
+    case json_type_double:
+    case json_type_string:
+    {
+        axiom_node_t* om_child_node = NULL;
+        axiom_node_t* om_text_node = NULL;
+
+        if (!axiom_element_create(env, NULL, child_name, NULL, &om_child_node))
+            return AXIS2_FAILURE;
+
+        if (!axiom_text_create(env, om_child_node, json_object_get_string(child_object),
+                          &om_text_node))
+                return AXIS2_FAILURE;
+
+        if (axiom_node_add_child(om_node, env, om_child_node) != AXIS2_SUCCESS)
+        {
+            axiom_node_free_tree(om_text_node, env);
+            return AXIS2_FAILURE;
+        }
+
+        break;
+    }
+
+    case json_type_null:
+    {
+        axiom_element_t* om_child_elem = NULL;
+        axiom_node_t* om_child_node = NULL;
+
+        /* handle as nillable */
+        axiom_attribute_t* attr;
+        axiom_namespace_t* ns =
+                axiom_namespace_create(env, AXIS2_JSON_XSI_URI, "xsi");
+
+        if (!ns)
+            return AXIS2_FAILURE;
+
+        om_child_elem = axiom_element_create(env, NULL, child_name, NULL, &om_child_node);
+        if (!om_child_elem)
+        {
+            axiom_namespace_free(ns, env);
+            return AXIS2_FAILURE;
+        }
+
+        if (axiom_node_add_child(om_node, env, om_child_node) != AXIS2_SUCCESS)
+        {
+            axiom_namespace_free(ns, env);
+            axiom_node_free_tree(om_child_node, env);
+            return AXIS2_FAILURE;
+        }
+
+        attr = axiom_attribute_create(env, "nil", "true", ns);
+        if (!attr)
+        {
+            axiom_attribute_free(attr, env);
+            return AXIS2_FAILURE;
+        }
+
+        if (axiom_element_add_attribute(om_child_elem, env, attr,
+                                        om_child_node) != AXIS2_SUCCESS)
+        {
+            axiom_attribute_free(attr, env);
+            return AXIS2_FAILURE;
+        }
+
+        break;
+    }
+    }
+
+    return AXIS2_SUCCESS;
+}
+
+axis2_status_t
+axis2_json_read_node(
+        json_object* parent,
+        const char* name,
+        axiom_node_t** om_node,
+        const axutil_env_t* env)
+{
+    if (!json_object_is_type(parent, json_type_object))
+        return AXIS2_FAILURE;
+
+    axiom_element_create(env, NULL, name, NULL, om_node);
+
+    json_object_object_foreach(parent, child_name, child_object)
+    {
+        if (axis2_json_read_child_node(child_object, child_name, *om_node, env) != AXIS2_SUCCESS)
+            return AXIS2_FAILURE;
+    }
+
+    return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_json_reader_t* AXIS2_CALL
+axis2_json_reader_create_for_stream(
+        const axutil_env_t* env,
+        axutil_stream_t* stream)
+{
+    axis2_json_reader_t* reader =
+            (axis2_json_reader_t*)AXIS2_MALLOC(env->allocator,
+                                               sizeof(struct axis2_json_reader));
+    if (reader)
+    {
+        axis2_char_t buffer[512];
+        int readed;
+        struct json_tokener* tokener = json_tokener_new();
+        enum json_tokener_error error;
+        json_object* json_obj = NULL;
+
+        reader->json_obj = NULL;
+        reader->axiom_node = NULL;
+        do
+        {
+            readed = axutil_stream_read(stream, env, &buffer, sizeof(buffer));
+            if (readed < 0)
+                break;
+
+            json_obj = json_tokener_parse_ex(tokener, buffer, readed);
+
+        } while ((error = json_tokener_get_error(tokener)) == json_tokener_continue);
+
+        if (error != json_tokener_success)
+        {
+            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_STATE_PARAM, AXIS2_FAILURE);
+            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Failed to parse JSON request: %s",
+                            json_tokener_error_to_str(tokener->err));
+            if (json_obj)
+                json_object_put(json_obj);
+            json_tokener_free(tokener);
+            free(reader);
+            return NULL;
+        }
+
+        reader->json_obj = json_obj;
+
+        json_tokener_free(tokener);
+    }
+
+    return reader;
+}
+
+
+AXIS2_EXTERN axis2_json_reader_t* AXIS2_CALL
+axis2_json_reader_create_for_memory(
+        const axutil_env_t* env,
+        const axis2_char_t* json_string,
+        int json_string_size)
+{
+    axis2_json_reader_t* reader =
+            (axis2_json_reader_t*)AXIS2_MALLOC(env->allocator,
+                                               sizeof(struct axis2_json_reader));
+    if (reader)
+    {
+        struct json_tokener* tokener = json_tokener_new();
+
+        reader->axiom_node = NULL;
+        reader->json_obj = json_tokener_parse_ex(tokener, json_string, json_string_size);
+        if (tokener->err != json_tokener_success)
+        {
+            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_STATE_PARAM, AXIS2_FAILURE);
+            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Failed to parse JSON request: %s",
+                            json_tokener_error_to_str(tokener->err));
+            if (reader->json_obj)
+                json_object_put(reader->json_obj);
+            json_tokener_free(tokener);
+            free(reader);
+            return NULL;
+        }
+        json_tokener_free(tokener);
+    }
+
+    return reader;
+}
+
+
+AXIS2_EXTERN void AXIS2_CALL
+axis2_json_reader_free(
+        axis2_json_reader_t* reader,
+        const axutil_env_t* env)
+{
+    if (reader->json_obj)
+        json_object_put(reader->json_obj);
+    AXIS2_FREE(env->allocator, reader);
+}
+
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axis2_json_reader_read(
+        axis2_json_reader_t* reader,
+        const axutil_env_t* env)
+{
+    json_object* json_root = NULL;
+    const char* json_root_name = NULL;
+
+    /* free existing om tree */
+    if (reader->axiom_node)
+        axiom_node_free_tree(reader->axiom_node, env);
+    reader->axiom_node = NULL;
+
+    /* get first child */
+    json_object_object_foreach(reader->json_obj, key, value)
+    {
+        json_root = value;
+        json_root_name = key;
+        break;
+    }
+
+    if (!json_root || !json_root_name)
+    {
+        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_STATE_PARAM, AXIS2_FAILURE);
+        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Failed find root JSON node");
+        return AXIS2_FAILURE;
+    }
+
+    return axis2_json_read_node(json_root, json_root_name, &reader->axiom_node, env);
+}
+
+
+AXIS2_EXTERN axiom_node_t* AXIS2_CALL
+axis2_json_reader_get_root_node(
+        axis2_json_reader_t* reader,
+        const axutil_env_t* env)
+{
+    (void)env;
+    return reader->axiom_node;
+}
diff --git a/src/core/transport/http/util/http_transport_utils.c b/src/core/transport/http/util/http_transport_utils.c
index c436da8..a360d88 100644
--- a/src/core/transport/http/util/http_transport_utils.c
+++ b/src/core/transport/http/util/http_transport_utils.c
@@ -44,6 +44,10 @@
 #include <axiom_mime_part.h>
 #include <axutil_class_loader.h>
 
+#ifdef AXIS2_JSON_ENABLED
+#include <axis2_json_reader.h>
+#endif
+
 #define AXIOM_MIME_BOUNDARY_BYTE 45
 
 /** Size of the buffer to be used when reading a file */
@@ -602,6 +606,50 @@
     axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE);
 
     char_set_str = axis2_http_transport_utils_get_charset_enc(env, content_type);
+
+    axis2_msg_ctx_set_charset_encoding(msg_ctx, env, char_set_str);
+
+#ifdef AXIS2_JSON_ENABLED
+    if (strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_JSON))
+    {
+        axis2_json_reader_t* json_reader = NULL;
+        axiom_soap_body_t* soap_body = NULL;
+        axiom_node_t* root_node = NULL;
+
+        json_reader = axis2_json_reader_create_for_stream(env, in_stream);
+        if (!json_reader)
+        {
+            axis2_json_reader_free(json_reader, env);
+            return AXIS2_FAILURE;
+        }
+
+        status = axis2_json_reader_read(json_reader, env);
+        if (status != AXIS2_SUCCESS)
+        {
+            axis2_json_reader_free(json_reader, env);
+            return status;
+        }
+
+        root_node = axis2_json_reader_get_root_node(json_reader, env);
+        if (!root_node)
+        {
+            axis2_json_reader_free(json_reader, env);
+            return AXIS2_FAILURE;
+        }
+
+        axis2_json_reader_free(json_reader, env);
+
+        soap_envelope =
+                axiom_soap_envelope_create_default_soap_envelope(env, AXIOM_SOAP11);
+        soap_body = axiom_soap_envelope_get_body(soap_envelope, env);
+        axiom_soap_body_add_child(soap_body, env, root_node);
+        axis2_msg_ctx_set_doing_json(msg_ctx, env, AXIS2_TRUE);
+        axis2_msg_ctx_set_doing_rest(msg_ctx, env, AXIS2_TRUE);
+        axis2_msg_ctx_set_rest_http_method(msg_ctx, env, AXIS2_HTTP_POST);
+    }
+    else
+    {
+#endif
     xml_reader = axiom_xml_reader_create_for_io(env, axis2_http_transport_utils_on_data_request,
         NULL, (void *)callback_ctx, axutil_string_get_buffer(char_set_str, env));
 
@@ -610,8 +658,6 @@
         return AXIS2_FAILURE;
     }
 
-    axis2_msg_ctx_set_charset_encoding(msg_ctx, env, char_set_str);
-
     om_builder = axiom_stax_builder_create(env, xml_reader);
     if(!om_builder)
     {
@@ -711,6 +757,9 @@
             }
         }
     }
+#ifdef AXIS2_JSON_ENABLED
+    }
+#endif
 
     if(do_rest)
     {
@@ -1058,6 +1107,49 @@
     axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE);
 
     char_set_str = axis2_http_transport_utils_get_charset_enc(env, content_type);
+
+#ifdef AXIS2_JSON_ENABLED
+    if (strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_JSON))
+    {
+        axis2_json_reader_t* json_reader = NULL;
+        axiom_soap_body_t* soap_body = NULL;
+        axiom_node_t* root_node = NULL;
+
+        json_reader = axis2_json_reader_create_for_stream(env, in_stream);
+        if (!json_reader)
+        {
+            axis2_json_reader_free(json_reader, env);
+            return AXIS2_FAILURE;
+        }
+
+        status = axis2_json_reader_read(json_reader, env);
+        if (status != AXIS2_SUCCESS)
+        {
+            axis2_json_reader_free(json_reader, env);
+            return status;
+        }
+
+        root_node = axis2_json_reader_get_root_node(json_reader, env);
+        if (!root_node)
+        {
+            axis2_json_reader_free(json_reader, env);
+            return AXIS2_FAILURE;
+        }
+
+        axis2_json_reader_free(json_reader, env);
+
+        soap_envelope =
+                axiom_soap_envelope_create_default_soap_envelope(env, AXIOM_SOAP11);
+        soap_body = axiom_soap_envelope_get_body(soap_envelope, env);
+        axiom_soap_body_add_child(soap_body, env, root_node);
+        axis2_msg_ctx_set_doing_json(msg_ctx, env, AXIS2_TRUE);
+        axis2_msg_ctx_set_doing_rest(msg_ctx, env, AXIS2_TRUE);
+        axis2_msg_ctx_set_rest_http_method(msg_ctx, env, AXIS2_HTTP_PUT);
+    }
+    else
+    {
+#endif
+
     xml_reader = axiom_xml_reader_create_for_io(env, axis2_http_transport_utils_on_data_request,
         NULL, (void *)callback_ctx, axutil_string_get_buffer(char_set_str, env));
 
@@ -1161,6 +1253,9 @@
             return AXIS2_FAILURE;
         }
     }
+#ifdef AXIS2_JSON_ENABLED
+    }
+#endif
 
     if(run_as_get)
     {
@@ -1292,6 +1387,14 @@
 
     axis2_msg_ctx_set_to(msg_ctx, env, axis2_endpoint_ref_create(env, request_uri));
     axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE);
+
+#ifdef AXIS2_JSON_ENABLED
+    if (strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_JSON))
+    {
+        axis2_msg_ctx_set_doing_json(msg_ctx, env, AXIS2_TRUE);
+    }
+    else
+#endif
     if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML))
     {
         if(soap_action_header)
@@ -1353,6 +1456,14 @@
 
     axis2_msg_ctx_set_to(msg_ctx, env, axis2_endpoint_ref_create(env, request_uri));
     axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE);
+
+#ifdef AXIS2_JSON_ENABLED
+    if (content_type && strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_JSON))
+    {
+        axis2_msg_ctx_set_doing_json(msg_ctx, env, AXIS2_TRUE);
+    }
+    else
+#endif
     if(content_type && strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML))
     {
         if(soap_action_header)
@@ -1415,6 +1526,14 @@
 
     axis2_msg_ctx_set_to(msg_ctx, env, axis2_endpoint_ref_create(env, request_uri));
     axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE);
+
+#ifdef AXIS2_JSON_ENABLED
+    if (strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_JSON))
+    {
+        axis2_msg_ctx_set_doing_json(msg_ctx, env, AXIS2_TRUE);
+    }
+    else
+#endif
     if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML))
     {
         if(soap_action_header)
diff --git a/src/core/util/core_utils.c b/src/core/util/core_utils.c
index 5ae9f31..cc34fcf 100644
--- a/src/core/util/core_utils.c
+++ b/src/core/util/core_utils.c
@@ -102,6 +102,9 @@
     axis2_svc_ctx_t *svc_ctx = NULL;
     axis2_bool_t doing_rest = AXIS2_FALSE;
     axis2_bool_t doing_mtom = AXIS2_FALSE;
+#ifdef AXIS2_JSON_ENABLED
+    axis2_bool_t doing_json = AXIS2_FALSE;
+#endif
     axis2_bool_t server_side = AXIS2_FALSE;
     axis2_svc_grp_ctx_t *svc_grp_ctx = NULL;
     axis2_char_t *msg_uuid = NULL;
@@ -217,6 +220,11 @@
     doing_mtom = axis2_msg_ctx_get_doing_mtom(in_msg_ctx, env);
     axis2_msg_ctx_set_doing_mtom(new_msg_ctx, env, doing_mtom);
 
+#ifdef AXIS2_JSON_ENABLED
+    doing_json = axis2_msg_ctx_get_doing_json(in_msg_ctx, env);
+    axis2_msg_ctx_set_doing_json(new_msg_ctx, env, doing_json);
+#endif
+
     server_side = axis2_msg_ctx_get_server_side(in_msg_ctx, env);
     axis2_msg_ctx_set_server_side(new_msg_ctx, env, server_side);
 
diff --git a/test/core/transport/http/Makefile.am b/test/core/transport/http/Makefile.am
index 85f24a4..1ba2c8e 100644
--- a/test/core/transport/http/Makefile.am
+++ b/test/core/transport/http/Makefile.am
@@ -36,3 +36,9 @@
 		 -I ../../../../axiom/include \
 		 -I ../../../cutest/include
 
+if AXIS2_JSON_ENABLED
+test_http_transport_LDADD += $(JSON_LIBS) \
+							$(top_builddir)/src/core/transport/http/common/libaxis2_http_common.la
+
+INCLUDES += $(JSON_CFLAGS)
+endif
diff --git a/test/core/transport/http/test_http_transport.c b/test/core/transport/http/test_http_transport.c
index 0416da8..6295db6 100644
--- a/test/core/transport/http/test_http_transport.c
+++ b/test/core/transport/http/test_http_transport.c
@@ -24,6 +24,13 @@
 #include <axis2_http_client.h>
 #include <cut_defs.h>
 #include <cut_http_server.h>
+#ifdef AXIS2_JSON_ENABLED
+#include <axiom.h>
+#include <axutil_utils.h>
+#include <json.h>
+#include <axis2_json_writer.h>
+#include <axis2_json_reader.h>
+#endif
 
 void
 test_http_request_line(
@@ -263,6 +270,152 @@
 #endif
 }
 
+#ifdef AXIS2_JSON_ENABLED
+void
+test_json(
+    const axutil_env_t * env)
+{
+    axiom_node_t* root_node = NULL;
+
+    /* JSON_C */
+    axis2_json_writer_t* json_writer;
+    axis2_json_reader_t* json_reader;
+    unsigned i;
+    axis2_char_t* xml_str;
+    const axis2_char_t* result_str;
+    int passed = 0;
+    int failed = 0;
+
+
+    const char* xml_data[] =
+    {
+        "<root><child1>value 1</child1><child2>value 2</child2></root>",
+        "<root> \t\r\n<child1>value 1</child1> <child2>value 2</child2>\n</root>",
+        "<root><child1><sub>value 1</sub></child1><child2>value 2</child2></root>",
+        "<root><child></child><ch>value 1</ch><ch>value 2</ch><ch>value 3</ch></root>",
+        "<root><child></child><ch><sub>11</sub><sub>12</sub></ch><ch><sub>11</sub><sub>12</sub></ch></root>",
+        "<root><ch xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:nil=\"true\"></ch></root>"
+    };
+
+    const char* json_data_mapped[] =
+    {
+        "{\"root\":{\"child1\":\"value 1\",\"child2\":\"value 2\"}}",
+        "{\"root\":{\"child1\":{\"sub\":\"value 1\"},\"child2\":\"value 2\"}}",
+        "{\"root\":{\"child\":\"\",\"ch\":[\"value 1\",\"value 2\",\"value 3\"]}}",
+        "{\"root\":{\"child\":\"\",\"ch\":[{\"sub\":[\"11\",\"12\"]},{\"sub\":[\"11\",\"12\"]}]}}",
+        "{\"root\":{\"ch\":null}}"
+    };
+
+    int xml2mapped[sizeof(xml_data) / sizeof(xml_data[0])] =
+    {
+        0, 0, 1, 2, 3, 4
+    };
+
+    int mapped2xml[sizeof(json_data_mapped) / sizeof(json_data_mapped[0])] =
+    {
+        0, 2, 3, 4, 5
+    };
+
+    printf(" ######################## testing xml -> json ########################## \n");
+
+    for (i = 0; i < sizeof(xml_data) / sizeof(xml_data[0]); ++i)
+    {
+        const char* xml = xml_data[i];
+
+        root_node = axiom_node_create_from_buffer(env, (axis2_char_t*)xml);
+
+        xml_str = axiom_node_to_string(root_node, env);
+
+        printf(" =============== source XML ================\n%s\n"
+               " ===========================================\n",
+               xml_str);
+        AXIS2_FREE(env->allocator, xml_str);
+
+        json_writer = axis2_json_writer_create(env);
+        axis2_json_writer_write(json_writer, root_node, env);
+
+        result_str = axis2_json_writer_get_json_string(json_writer, env, 0);
+        printf(" ============= resulting JSON ==============\n%s\n"
+               " ===========================================\n",
+               result_str);
+
+        if (strcmp(result_str, json_data_mapped[xml2mapped[i]]))
+        {
+            ++failed;
+            printf("TEST FAILED\nexpected result: %s\n", json_data_mapped[xml2mapped[i]]);
+        }
+        else
+        {
+            ++passed;
+            printf("test passed\n\n");
+        }
+
+        axis2_json_writer_free(json_writer, env);
+
+        axiom_node_free_tree(root_node, env);
+    }
+
+
+    printf(" ######################## testing json -> xml ########################## \n");
+
+    for (i = 0; i < sizeof(json_data_mapped) / sizeof(json_data_mapped[0]); ++i)
+    {
+        const char* json = json_data_mapped[i];
+        int length = strlen(json);
+
+        json_reader = axis2_json_reader_create_for_memory(env, json, length);
+        if (!json_reader)
+        {
+            printf("Failed to create json_reader");
+            return;
+        }
+
+        if (axis2_json_reader_read(json_reader, env) != AXIS2_SUCCESS)
+        {
+            printf("Failed to axis2_json_reader_read");
+            return;
+        }
+
+        root_node = axis2_json_reader_get_root_node(json_reader, env);
+        if (!root_node)
+        {
+            printf("Failed to get root_node");
+            return;
+        }
+
+
+        printf(" =============== source JSON ================\n%s\n"
+               " ===========================================\n",
+               json);
+
+
+        xml_str = axiom_node_to_string(root_node, env);
+
+        printf(" =============== resulting XML ================\n%s\n"
+               " ===========================================\n",
+               xml_str);
+
+        if (strcmp(xml_str, xml_data[mapped2xml[i]]))
+        {
+            ++failed;
+            printf("TEST FAILED\nExpected result: %s\n", xml_data[mapped2xml[i]]);
+        }
+        else
+        {
+            ++passed;
+            printf("test passed\n\n");
+        }
+        AXIS2_FREE(env->allocator, xml_str);
+
+        axis2_json_reader_free(json_reader, env);
+        axiom_node_free_tree(root_node, env);
+    }
+
+    printf("JSON tests passed: %d, failed: %d\n", passed, failed);
+}
+#endif
+
+
 int
 main(
     void)
@@ -276,6 +429,9 @@
        test_http_client(env);
        test_https_client(env);
        test_url(env);
+#ifdef AXIS2_JSON_ENABLED
+       test_json(env);
+#endif
        axutil_env_free(env);
 	}
     CUT_RETURN_ON_FAILURE(-1);