aJson is the attempt to port a complete JSON implementation to Arduino. It is based on the cJSON implementation, reduced in size and removing one or two feature. The current mbed implementation only supports FILE* as input so you will have to use a temporary file for parsing your json input. https://github.com/interactive-matter/aJson

Dependents:   WIZwikiREST20

Revision:
0:428cf9a51873
Child:
1:6df1d1f1b372
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aJSON.cpp	Mon Aug 27 15:15:45 2012 +0000
@@ -0,0 +1,1201 @@
+/*
+ Copyright (c) 2001, Interactive Matter, Marcus Nowotny
+
+ Based on the cJSON Library, Copyright (C) 2009 Dave Gamble
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+// aJSON
+// aJson Library for Arduino.
+// This library is suited for Atmega328 based Arduinos.
+// The RAM on ATmega168 based Arduinos is too limited
+
+/******************************************************************************
+ * Includes
+ ******************************************************************************/
+
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+#include <ctype.h>
+//#include <avr/pgmspace.h>
+#include "aJSON.h"
+#include "utility/streamhelper.h"
+#include "utility/stringbuffer.h"
+
+#include "compatibility.h"
+#include "stdio.h"
+
+/******************************************************************************
+ * Definitions
+ ******************************************************************************/
+//Default buffer sizes - buffers get initialized and grow acc to that size
+#define BUFFER_DEFAULT_SIZE 4
+
+//how much digits after . for float
+#define FLOAT_PRECISION 5
+
+
+
+
+
+
+// Internal constructor.
+aJsonObject*
+aJsonClass::newItem()
+{
+  aJsonObject* node = (aJsonObject*) malloc(sizeof(aJsonObject));
+  if (node)
+    memset(node, 0, sizeof(aJsonObject));
+  return node;
+}
+
+// Delete a aJsonObject structure.
+void
+aJsonClass::deleteItem(aJsonObject *c)
+{
+  aJsonObject *next;
+  while (c)
+    {
+      next = c->next;
+      if (!(c->type & aJson_IsReference) && c->child)
+        {
+          deleteItem(c->child);
+        }
+      if ((c->type == aJson_String) && c->valuestring)
+        {
+          free(c->valuestring);
+        }
+      if (c->name)
+        {
+          free(c->name);
+        }
+      free(c);
+      c = next;
+    }
+}
+
+// Parse the input text to generate a number, and populate the result into item.
+int
+aJsonClass::parseNumber(aJsonObject *item, FILE* stream)
+{
+  int i = 0;
+  char sign = 1;
+
+  int in = fgetc(stream);
+  if (in == EOF)
+    {
+      return EOF;
+    }
+  // It is easier to decode ourselves than to use sscnaf,
+  // since so we can easier decide between int & double
+  if (in == '-')
+    {
+      //it is a negative number
+      sign = -1;
+      in = fgetc(stream);
+      if (in == EOF)
+        {
+          return EOF;
+        }
+    }
+  if (in >= '0' && in <= '9')
+    do
+      {
+        i = (i * 10) + (in - '0');
+        in = fgetc(stream);
+      }
+    while (in >= '0' && in <= '9'); // Number?
+  //end of integer part &#65533; or isn't it?
+  if (!(in == '.' || in == 'e' || in == 'E'))
+    {
+      item->valueint = i * (int) sign;
+      item->type = aJson_Int;
+    }
+  //ok it seems to be a double
+  else
+    {
+      double n = (double) i;
+      int scale = 0;
+      int subscale = 0;
+      char signsubscale = 1;
+      if (in == '.')
+        {
+          in = fgetc(stream);
+          do
+            {
+              n = (n * 10.0) + (in - '0'), scale--;
+              in = fgetc(stream);
+            }
+          while (in >= '0' && in <= '9');
+        } // Fractional part?
+      if (in == 'e' || in == 'E') // Exponent?
+        {
+          in = fgetc(stream);
+          if (in == '+')
+            {
+              in = fgetc(stream);
+            }
+          else if (in == '-')
+            {
+              signsubscale = -1;
+              in = fgetc(stream);
+            }
+          while (in >= '0' && in <= '9')
+            {
+              subscale = (subscale * 10) + (in - '0'); // Number?
+              in = fgetc(stream);
+            }
+        }
+
+      n = sign * n * pow(10.0, ((double) scale + (double) subscale
+          * (double) signsubscale)); // number = +/- number.fraction * 10^+/- exponent
+
+      item->valuefloat = n;
+      item->type = aJson_Float;
+    }
+  //preserve the last character for the next routine
+  ungetc(in, stream);
+  return 0;
+}
+
+// Render the number nicely from the given item into a string.
+int
+aJsonClass::printInt(aJsonObject *item, FILE* stream)
+{
+  if (item != NULL)
+    {
+      return fprintf_P(stream, PSTR("%d"), item->valueint);
+    }
+  //printing nothing is ok
+  return 0;
+}
+
+int
+aJsonClass::printFloat(aJsonObject *item, FILE* stream)
+{
+  if (item != NULL)
+    {
+      double d = item->valuefloat;
+      if (d<0.0) {
+          fprintf_P(stream,PSTR("-"));
+          d=-d;
+      }
+      //print the integer part
+      unsigned long integer_number = (unsigned long)d;
+      fprintf_P(stream,PSTR("%u."),integer_number);
+      //print the fractional part
+      double fractional_part = d - ((double)integer_number);
+      //we do a do-while since we want to print at least one zero
+      //we just support a certain number of digits after the '.'
+      int n = FLOAT_PRECISION;
+      fractional_part += 0.5/pow(10.0, FLOAT_PRECISION);
+      do {
+          //make the first digit non fractional(shift it before the '.'
+          fractional_part *= 10.0;
+          //create an int out of it
+          unsigned int digit = (unsigned int) fractional_part;
+          //print it
+          fprintf_P(stream,PSTR("%u"),digit);
+          //remove it from the number
+          fractional_part -= (double)digit;
+          n--;
+      } while ((fractional_part!=0) && (n>0));
+    }
+  //printing nothing is ok
+  return 0;
+}
+
+// Parse the input text into an unescaped cstring, and populate item.
+int
+aJsonClass::parseString(aJsonObject *item, FILE* stream)
+{
+  //we do not need to skip here since the first byte should be '\"'
+  int in = fgetc(stream);
+  if (in != '\"')
+    {
+      return EOF; // not a string!
+    }
+  item->type = aJson_String;
+  //allocate a buffer & track how long it is and how much we have read
+  string_buffer* buffer = stringBufferCreate();
+  if (buffer == NULL)
+    {
+      //unable to allocate the string
+      return EOF;
+    }
+  in = fgetc(stream);
+  if (in == EOF)
+    {
+      stringBufferFree(buffer);
+      return EOF;
+    }
+  while (in != EOF)
+    {
+      while (in != '\"' && in >= 32)
+        {
+          if (in != '\\')
+            {
+              stringBufferAdd((char) in, buffer);
+            }
+          else
+            {
+              in = fgetc(stream);
+              if (in == EOF)
+                {
+                  stringBufferFree(buffer);
+                  return EOF;
+                }
+              switch (in)
+                {
+              case '\\':
+                stringBufferAdd('\\', buffer);
+                break;
+              case '\"':
+                stringBufferAdd('\"', buffer);
+                break;
+              case 'b':
+                stringBufferAdd('\b', buffer);
+                break;
+              case 'f':
+                stringBufferAdd('\f', buffer);
+                break;
+              case 'n':
+                stringBufferAdd('\n', buffer);
+                break;
+              case 'r':
+                stringBufferAdd('\r', buffer);
+                break;
+              case 't':
+                stringBufferAdd('\t', buffer);
+                break;
+              default:
+                //we do not understand it so we skip it
+                break;
+                }
+            }
+          in = fgetc(stream);
+          if (in == EOF)
+            {
+              stringBufferFree(buffer);
+              return EOF;
+            }
+        }
+      //the string ends here
+      item->valuestring = stringBufferToString(buffer);
+      return 0;
+    }
+  //we should not be here but it is ok
+  return 0;
+}
+
+// Render the cstring provided to an escaped version that can be printed.
+int
+aJsonClass::printStringPtr(const char *str, FILE* stream)
+{
+  if (fputc('\"', stream) == EOF)
+    {
+      return EOF;
+    }
+  char* ptr = (char*) str;
+  if (ptr != NULL)
+    {
+      while (*ptr != 0)
+        {
+          if ((unsigned char) *ptr > 31 && *ptr != '\"' && *ptr != '\\')
+            {
+              if (fputc(*ptr, stream) == EOF)
+                {
+                  return EOF;
+                }
+              ptr++;
+            }
+          else
+            {
+              if (fputc('\\', stream) == EOF)
+                {
+                  return EOF;
+                }
+              switch (*ptr++)
+                {
+              case '\\':
+                if (fputc('\\', stream) == EOF)
+                  {
+                    return EOF;
+                  }
+                break;
+              case '\"':
+                if (fputc('\"', stream) == EOF)
+                  {
+                    return EOF;
+                  }
+                break;
+              case '\b':
+                if (fputc('b', stream) == EOF)
+                  {
+                    return EOF;
+                  }
+                break;
+              case '\f':
+                if (fputc('f', stream) == EOF)
+                  {
+                    return EOF;
+                  }
+                break;
+              case '\n':
+                if (fputc('n', stream) == EOF)
+                  {
+                    return EOF;
+                  }
+                break;
+              case '\r':
+                if (fputc('r', stream) == EOF)
+                  {
+                    return EOF;
+                  }
+                break;
+              case '\t':
+                if (fputc('t', stream) == EOF)
+                  {
+                    return EOF;
+                  }
+                break;
+              default:
+                break; // eviscerate with prejudice.
+                }
+            }
+
+        }
+    }
+  if (fputc('\"', stream) == EOF)
+    {
+      return EOF;
+    }
+  return 0;
+}
+
+// Invote print_string_ptr (which is useful) on an item.
+int
+aJsonClass::printString(aJsonObject *item, FILE* stream)
+{
+  return printStringPtr(item->valuestring, stream);
+}
+
+// Utility to jump whitespace and cr/lf
+int
+aJsonClass::skip(FILE* stream)
+{
+  if (stream == NULL)
+    {
+      return EOF;
+    }
+  int in = fgetc(stream);
+  while (in != EOF && (in <= 32))
+    {
+      in = fgetc(stream);
+    }
+  if (in != EOF)
+    {
+      if (ungetc(in, stream) == EOF)
+        {
+          return EOF;
+        }
+      return 0;
+    }
+  return EOF;
+}
+
+// Parse an object - create a new root, and populate.
+/*aJsonObject*
+aJsonClass::parse(char *value)
+{
+  FILE* string_input_stream = openStringInputStream(value);
+  aJsonObject* result = parse(string_input_stream, NULL);
+  closeStringInputStream(string_input_stream);
+  return result;
+}*/
+
+// Parse an object - create a new root, and populate.
+aJsonObject*
+aJsonClass::parse(FILE* stream)
+{
+  return parse(stream, NULL);
+}
+
+// Parse an object - create a new root, and populate.
+aJsonObject*
+aJsonClass::parse(FILE* stream, char** filter)
+{
+  if (stream == NULL)
+    {
+      return NULL;
+    }
+  aJsonObject *c = newItem();
+  if (!c)
+    return NULL; /* memory fail */
+
+  skip(stream);
+  if (parseValue(c, stream, filter) == EOF)
+    {
+      deleteItem(c);
+      return NULL;
+    }
+  return c;
+}
+
+// Render a aJsonObject item/entity/structure to text.
+int
+aJsonClass::print(aJsonObject* item, FILE* stream)
+{
+  return printValue(item, stream);
+}
+
+/*char*
+aJsonClass::print(aJsonObject* item)
+{
+  FILE* stream = openStringOutputStream();
+  if (stream == NULL)
+    {
+      return NULL;
+    }
+  print(item, stream);
+  return closeStringOutputStream(stream);
+}*/
+
+// Parser core - when encountering text, process appropriately.
+int
+aJsonClass::parseValue(aJsonObject *item, FILE* stream, char** filter)
+{
+  if (stream == NULL)
+    {
+      return EOF; // Fail on null.
+    }
+  if (skip(stream) == EOF)
+    {
+      return EOF;
+    }
+  //read the first byte from the stream
+  int in = fgetc(stream);
+  if (in == EOF)
+    {
+      return EOF;
+    }
+  if (ungetc(in, stream) == EOF)
+    {
+      return EOF;
+    }
+  if (in == '\"')
+    {
+      return parseString(item, stream);
+    }
+  else if (in == '-' || (in >= '0' && in <= '9'))
+    {
+      return parseNumber(item, stream);
+    }
+  else if (in == '[')
+    {
+      return parseArray(item, stream, filter);
+    }
+  else if (in == '{')
+    {
+      return parseObject(item, stream, filter);
+    }
+  //it can only be null, false or true
+  else if (in == 'n')
+    {
+      //a buffer to read the value
+      char buffer[] =
+        { 0, 0, 0, 0 };
+      if (fread(buffer, sizeof(char), 4, stream) != 4)
+        {
+          return EOF;
+        }
+      if (!strncmp(buffer, "null", 4))
+        {
+          item->type = aJson_NULL;
+          return 0;
+        }
+      else
+        {
+          return EOF;
+        }
+    }
+  else if (in == 'f')
+    {
+      //a buffer to read the value
+      char buffer[] =
+        { 0, 0, 0, 0, 0 };
+      if (fread(buffer, sizeof(char), 5, stream) != 5)
+        {
+          return EOF;
+        }
+      if (!strncmp(buffer, "false", 5))
+        {
+          item->type = aJson_False;
+          item->valuebool = 0;
+          return 0;
+        }
+    }
+  else if (in == 't')
+    {
+      //a buffer to read the value
+      char buffer[] =
+        { 0, 0, 0, 0 };
+      if (fread(buffer, sizeof(char), 4, stream) != 4)
+        {
+          return EOF;
+        }
+      if (!strncmp(buffer, "true", 4))
+        {
+          item->type = aJson_True;
+          item->valuebool = -1;
+          return 0;
+        }
+    }
+
+  return EOF; // failure.
+}
+
+// Render a value to text.
+int
+aJsonClass::printValue(aJsonObject *item, FILE* stream)
+{
+  int result = 0;
+  if (item == NULL)
+    {
+      //nothing to do
+      return 0;
+    }
+  switch (item->type)
+    {
+  case aJson_NULL:
+    result = fprintf_P(stream, PSTR("null"));
+    break;
+  case aJson_False:
+    result = fprintf_P(stream, PSTR("false"));
+    break;
+  case aJson_True:
+    result = fprintf_P(stream, PSTR("true"));
+    break;
+  case aJson_Int:
+    result = printInt(item, stream);
+    break;
+  case aJson_Float:
+    result = printFloat(item, stream);
+    break;
+  case aJson_String:
+    result = printString(item, stream);
+    break;
+  case aJson_Array:
+    result = printArray(item, stream);
+    break;
+  case aJson_Object:
+    result = printObject(item, stream);
+    break;
+    }
+  //good time to flush the stream
+  fflush(stream);
+  return result;
+}
+
+// Build an array from input text.
+int
+aJsonClass::parseArray(aJsonObject *item, FILE* stream, char** filter)
+{
+  int in = fgetc(stream);
+  if (in != '[')
+    {
+      return EOF; // not an array!
+    }
+
+  item->type = aJson_Array;
+  skip(stream);
+  in = fgetc(stream);
+  //check for empty array
+  if (in == ']')
+    {
+      return 0; // empty array.
+    }
+  //now put back the last character
+  ungetc(in, stream);
+  aJsonObject *child;
+  char first = -1;
+  while ((first) || (in == ','))
+    {
+      aJsonObject *new_item = newItem();
+      if (new_item == NULL)
+        {
+          return EOF; // memory fail
+        }
+      if (first)
+        {
+          item->child = new_item;
+          first = 0;
+        }
+      else
+        {
+          child->next = new_item;
+          new_item->prev = child;
+        }
+      child = new_item;
+      skip(stream);
+      if (parseValue(child, stream, filter))
+        {
+          return EOF;
+        }
+      skip(stream);
+      in = fgetc(stream);
+    }
+  if (in == ']')
+    {
+      return 0; // end of array
+    }
+  else
+    {
+      return EOF; // malformed.
+    }
+}
+
+// Render an array to text
+int
+aJsonClass::printArray(aJsonObject *item, FILE* stream)
+{
+  if (item == NULL)
+    {
+      //nothing to do
+      return 0;
+    }
+  aJsonObject *child = item->child;
+  if (fputc('[', stream) == EOF)
+    {
+      return EOF;
+    }
+  while (child)
+    {
+      if (printValue(child, stream) == EOF)
+        {
+          return EOF;
+        }
+      child = child->next;
+      if (child)
+        {
+          if (fputc(',', stream) == EOF)
+            {
+              return EOF;
+            }
+        }
+    }
+  if (fputc(']', stream) == EOF)
+    {
+      return EOF;
+    }
+  return 0;
+}
+
+// Build an object from the text.
+int
+aJsonClass::parseObject(aJsonObject *item, FILE* stream, char** filter)
+{
+  int in = fgetc(stream);
+  if (in != '{')
+    {
+      return EOF; // not an object!
+    }
+
+  item->type = aJson_Object;
+  skip(stream);
+  //check for an empty object
+  in = fgetc(stream);
+  if (in == '}')
+    {
+      return 0; // empty object.
+    }
+  //preserve the char for the next parser
+  ungetc(in, stream);
+
+  aJsonObject* child;
+  char first = -1;
+  while ((first) || (in == ','))
+    {
+      //in = fgetc(stream);
+      aJsonObject* new_item = newItem();
+      if (new_item == NULL)
+        {
+          return EOF; // memory fail
+        }
+      if (first)
+        {
+          first = 0;
+          item->child = new_item;
+        }
+      else
+        {
+          child->next = new_item;
+          new_item->prev = child;
+        }
+      child = new_item;
+      skip(stream);
+      if (parseString(child, stream) == EOF)
+        {
+          return EOF;
+        }
+      skip(stream);
+      child->name = child->valuestring;
+      child->valuestring = NULL;
+
+      in = fgetc(stream);
+      if (in != ':')
+        {
+          return EOF; // fail!
+        }
+      // skip any spacing, get the value.
+      skip(stream);
+      if (parseValue(child, stream, filter) == EOF)
+        {
+          return EOF;
+        }
+      in = fgetc(stream);
+    }
+
+  if (in == '}')
+    {
+      return 0; // end of array
+    }
+  else
+    {
+      return EOF; // malformed.
+    }
+}
+
+// Render an object to text.
+int
+aJsonClass::printObject(aJsonObject *item, FILE* stream)
+{
+  if (item == NULL)
+    {
+      //nothing to do
+      return 0;
+    }
+  aJsonObject *child = item->child;
+  if (fputc('{', stream) == EOF)
+    {
+      return EOF;
+    }
+  while (child)
+    {
+      if (printStringPtr(child->name, stream) == EOF)
+        {
+          return EOF;
+        }
+      if (fputc(':', stream) == EOF)
+        {
+          return EOF;
+        }
+      if (printValue(child, stream) == EOF)
+        {
+          return EOF;
+        }
+      child = child->next;
+      if (child)
+        {
+          if (fputc(',', stream) == EOF)
+            {
+              return EOF;
+            }
+        }
+    }
+  if (fputc('}', stream) == EOF)
+    {
+      return EOF;
+    }
+  return 0;
+}
+
+// Get Array size/item / object item.
+unsigned char
+aJsonClass::getArraySize(aJsonObject *array)
+{
+  aJsonObject *c = array->child;
+  unsigned char i = 0;
+  while (c)
+    i++, c = c->next;
+  return i;
+}
+aJsonObject*
+aJsonClass::getArrayItem(aJsonObject *array, unsigned char item)
+{
+  aJsonObject *c = array->child;
+  while (c && item > 0)
+    item--, c = c->next;
+  return c;
+}
+aJsonObject*
+aJsonClass::getObjectItem(aJsonObject *object, const char *string)
+{
+  aJsonObject *c = object->child;
+  while (c && strcasecmp(c->name, string))
+    c = c->next;
+  return c;
+}
+
+// Utility for array list handling.
+void
+aJsonClass::suffixObject(aJsonObject *prev, aJsonObject *item)
+{
+  prev->next = item;
+  item->prev = prev;
+}
+// Utility for handling references.
+aJsonObject*
+aJsonClass::createReference(aJsonObject *item)
+{
+  aJsonObject *ref = newItem();
+  if (!ref)
+    return 0;
+  memcpy(ref, item, sizeof(aJsonObject));
+  ref->name = 0;
+  ref->type |= aJson_IsReference;
+  ref->next = ref->prev = 0;
+  return ref;
+}
+
+// Add item to array/object.
+void
+aJsonClass::addItemToArray(aJsonObject *array, aJsonObject *item)
+{
+  aJsonObject *c = array->child;
+  if (!item)
+    return;
+  if (!c)
+    {
+      array->child = item;
+    }
+  else
+    {
+      while (c && c->next)
+        c = c->next;
+      suffixObject(c, item);
+    }
+}
+void
+aJsonClass::addItemToObject(aJsonObject *object, const char *string,
+    aJsonObject *item)
+{
+  if (!item)
+    return;
+  if (item->name)
+    free(item->name);
+  item->name = strdup(string);
+  addItemToArray(object, item);
+}
+void
+aJsonClass::addItemReferenceToArray(aJsonObject *array, aJsonObject *item)
+{
+  addItemToArray(array, createReference(item));
+}
+void
+aJsonClass::addItemReferenceToObject(aJsonObject *object, const char *string,
+    aJsonObject *item)
+{
+  addItemToObject(object, string, createReference(item));
+}
+
+aJsonObject*
+aJsonClass::detachItemFromArray(aJsonObject *array, unsigned char which)
+{
+  aJsonObject *c = array->child;
+  while (c && which > 0)
+    c = c->next, which--;
+  if (!c)
+    return 0;
+  if (c->prev)
+    c->prev->next = c->next;
+  if (c->next)
+    c->next->prev = c->prev;
+  if (c == array->child)
+    array->child = c->next;
+  c->prev = c->next = 0;
+  return c;
+}
+void
+aJsonClass::deleteItemFromArray(aJsonObject *array, unsigned char which)
+{
+  deleteItem(detachItemFromArray(array, which));
+}
+aJsonObject*
+aJsonClass::detachItemFromObject(aJsonObject *object, const char *string)
+{
+  unsigned char i = 0;
+  aJsonObject *c = object->child;
+  while (c && strcasecmp(c->name, string))
+    i++, c = c->next;
+  if (c)
+    return detachItemFromArray(object, i);
+  return 0;
+}
+void
+aJsonClass::deleteItemFromObject(aJsonObject *object, const char *string)
+{
+  deleteItem(detachItemFromObject(object, string));
+}
+
+// Replace array/object items with new ones.
+void
+aJsonClass::replaceItemInArray(aJsonObject *array, unsigned char which,
+    aJsonObject *newitem)
+{
+  aJsonObject *c = array->child;
+  while (c && which > 0)
+    c = c->next, which--;
+  if (!c)
+    return;
+  newitem->next = c->next;
+  newitem->prev = c->prev;
+  if (newitem->next)
+    newitem->next->prev = newitem;
+  if (c == array->child)
+    array->child = newitem;
+  else
+    newitem->prev->next = newitem;
+  c->next = c->prev = 0;
+  deleteItem(c);
+}
+void
+aJsonClass::replaceItemInObject(aJsonObject *object, const char *string,
+    aJsonObject *newitem)
+{
+  unsigned char i = 0;
+  aJsonObject *c = object->child;
+  while (c && strcasecmp(c->name, string))
+    i++, c = c->next;
+  if (c)
+    {
+      newitem->name = strdup(string);
+      replaceItemInArray(object, i, newitem);
+    }
+}
+
+// Create basic types:
+aJsonObject*
+aJsonClass::createNull()
+{
+  aJsonObject *item = newItem();
+  if (item)
+    item->type = aJson_NULL;
+  return item;
+}
+
+aJsonObject*
+aJsonClass::createTrue()
+{
+  aJsonObject *item = newItem();
+  if (item)
+    {
+      item->type = aJson_True;
+      item->valuebool = -1;
+    }
+  return item;
+}
+aJsonObject*
+aJsonClass::createFalse()
+{
+  aJsonObject *item = newItem();
+  if (item)
+    {
+      item->type = aJson_False;
+      item->valuebool = 0;
+    }
+  return item;
+}
+aJsonObject*
+aJsonClass::createItem(char b)
+{
+  aJsonObject *item = newItem();
+  if (item)
+    {
+      item->type = b ? aJson_True : aJson_False;
+      item->valuebool = b ? -1 : 0;
+    }
+  return item;
+}
+
+aJsonObject*
+aJsonClass::createItem(int num)
+{
+  aJsonObject *item = newItem();
+  if (item)
+    {
+      item->type = aJson_Int;
+      item->valueint = (int) num;
+    }
+  return item;
+}
+
+aJsonObject*
+aJsonClass::createItem(double num)
+{
+  aJsonObject *item = newItem();
+  if (item)
+    {
+      item->type = aJson_Float;
+      item->valuefloat = num;
+    }
+  return item;
+}
+
+aJsonObject*
+aJsonClass::createItem(const char *string)
+{
+  aJsonObject *item = newItem();
+  if (item)
+    {
+      item->type = aJson_String;
+      item->valuestring = strdup(string);
+    }
+  return item;
+}
+
+aJsonObject*
+aJsonClass::createArray()
+{
+  aJsonObject *item = newItem();
+  if (item)
+    item->type = aJson_Array;
+  return item;
+}
+aJsonObject*
+aJsonClass::createObject()
+{
+  aJsonObject *item = newItem();
+  if (item)
+    item->type = aJson_Object;
+  return item;
+}
+
+// Create Arrays:
+aJsonObject*
+aJsonClass::createIntArray(int *numbers, unsigned char count)
+{
+  unsigned char i;
+  aJsonObject *n = 0, *p = 0, *a = createArray();
+  for (i = 0; a && i < count; i++)
+    {
+      n = createItem(numbers[i]);
+      if (!i)
+        a->child = n;
+      else
+        suffixObject(p, n);
+      p = n;
+    }
+  return a;
+}
+
+aJsonObject*
+aJsonClass::createFloatArray(double *numbers, unsigned char count)
+{
+  unsigned char i;
+  aJsonObject *n = 0, *p = 0, *a = createArray();
+  for (i = 0; a && i < count; i++)
+    {
+      n = createItem(numbers[i]);
+      if (!i)
+        a->child = n;
+      else
+        suffixObject(p, n);
+      p = n;
+    }
+  return a;
+}
+
+aJsonObject*
+aJsonClass::createDoubleArray(double *numbers, unsigned char count)
+{
+  unsigned char i;
+  aJsonObject *n = 0, *p = 0, *a = createArray();
+  for (i = 0; a && i < count; i++)
+    {
+      n = createItem(numbers[i]);
+      if (!i)
+        a->child = n;
+      else
+        suffixObject(p, n);
+      p = n;
+    }
+  return a;
+}
+
+aJsonObject*
+aJsonClass::createStringArray(const char **strings, unsigned char count)
+{
+  unsigned char i;
+  aJsonObject *n = 0, *p = 0, *a = createArray();
+  for (i = 0; a && i < count; i++)
+    {
+      n = createItem(strings[i]);
+      if (!i)
+        a->child = n;
+      else
+        suffixObject(p, n);
+      p = n;
+    }
+  return a;
+}
+
+void
+aJsonClass::addNullToObject(aJsonObject* object, const char* name)
+{
+  addItemToObject(object, name, createNull());
+}
+
+void
+aJsonClass::addTrueToObject(aJsonObject* object, const char* name)
+{
+  addItemToObject(object, name, createTrue());
+}
+
+void
+aJsonClass::addFalseToObject(aJsonObject* object, const char* name)
+{
+  addItemToObject(object, name, createFalse());
+}
+
+void
+aJsonClass::addNumberToObject(aJsonObject* object, const char* name, int n)
+{
+  addItemToObject(object, name, createItem(n));
+}
+
+void
+aJsonClass::addNumberToObject(aJsonObject* object, const char* name, double n)
+{
+  addItemToObject(object, name, createItem(n));
+}
+
+void
+aJsonClass::addStringToObject(aJsonObject* object, const char* name,
+    const char* s)
+{
+  addItemToObject(object, name, createItem(s));
+}
+
+//TODO conversion routines btw. float & int types?
+
+aJsonClass aJson;