private static void buildJSONString(StringBuilder sb, Object o, ObjectInspector oi) throws IOException {

    switch (oi.getCategory()) {
    case PRIMITIVE: {
      PrimitiveObjectInspector poi = (PrimitiveObjectInspector) oi;
      if (o == null) {
        sb.append("null");
      } else {
        switch (poi.getPrimitiveCategory()) {
        case BOOLEAN: {
          boolean b = ((BooleanObjectInspector) poi).get(o);
          sb.append(b ? "true" : "false");
          break;
        }
        case BYTE: {
          sb.append(((ByteObjectInspector) poi).get(o));
          break;
        }
        case SHORT: {
          sb.append(((ShortObjectInspector) poi).get(o));
          break;
        }
        case INT: {
          sb.append(((IntObjectInspector) poi).get(o));
          break;
        }
        case LONG: {
          sb.append(((LongObjectInspector) poi).get(o));
          break;
        }
        case FLOAT: {
          sb.append(((FloatObjectInspector) poi).get(o));
          break;
        }
        case DOUBLE: {
          sb.append(((DoubleObjectInspector) poi).get(o));
          break;
        }
        case STRING: {
          String s =
                  SerDeUtils.escapeString(((StringObjectInspector) poi).getPrimitiveJavaObject(o));
          appendWithQuotes(sb, s);
          break;
        }
        case BINARY: {
          throw new IOException("JsonSerDe does not support BINARY type");
        }
        case DATE:
          Date d = ((DateObjectInspector)poi).getPrimitiveJavaObject(o);
          appendWithQuotes(sb, d.toString());
          break;
        case TIMESTAMP: {
          Timestamp t = ((TimestampObjectInspector) poi).getPrimitiveJavaObject(o);
          appendWithQuotes(sb, t.toString());
          break;
        }
        case DECIMAL:
          sb.append(((HiveDecimalObjectInspector)poi).getPrimitiveJavaObject(o));
          break;
        case VARCHAR: {
          String s = SerDeUtils.escapeString(
              ((HiveVarcharObjectInspector) poi).getPrimitiveJavaObject(o).toString());
          appendWithQuotes(sb, s);
          break;
        }
        case CHAR: {
          //this should use HiveChar.getPaddedValue() but it's protected; currently (v0.13)
          // HiveChar.toString() returns getPaddedValue()
          String s = SerDeUtils.escapeString(
              ((HiveCharObjectInspector) poi).getPrimitiveJavaObject(o).toString());
          appendWithQuotes(sb, s);
          break;
        }
        default:
          throw new RuntimeException("Unknown primitive type: " + poi.getPrimitiveCategory());
        }
      }
      break;
    }
    case LIST: {
      ListObjectInspector loi = (ListObjectInspector) oi;
      ObjectInspector listElementObjectInspector = loi
        .getListElementObjectInspector();
      List<?> olist = loi.getList(o);
      if (olist == null) {
        sb.append("null");
      } else {
        sb.append(SerDeUtils.LBRACKET);
        for (int i = 0; i < olist.size(); i++) {
          if (i > 0) {
            sb.append(SerDeUtils.COMMA);
          }
          buildJSONString(sb, olist.get(i), listElementObjectInspector);
        }
        sb.append(SerDeUtils.RBRACKET);
      }
      break;
    }
    case MAP: {
      MapObjectInspector moi = (MapObjectInspector) oi;
      ObjectInspector mapKeyObjectInspector = moi.getMapKeyObjectInspector();
      ObjectInspector mapValueObjectInspector = moi
        .getMapValueObjectInspector();
      Map<?, ?> omap = moi.getMap(o);
      if (omap == null) {
        sb.append("null");
      } else {
        sb.append(SerDeUtils.LBRACE);
        boolean first = true;
        for (Object entry : omap.entrySet()) {
          if (first) {
            first = false;
          } else {
            sb.append(SerDeUtils.COMMA);
          }
          Map.Entry<?, ?> e = (Map.Entry<?, ?>) entry;
          StringBuilder keyBuilder = new StringBuilder();
          buildJSONString(keyBuilder, e.getKey(), mapKeyObjectInspector);
          String keyString = keyBuilder.toString().trim();
          if((!keyString.isEmpty()) && (keyString.charAt(0) != SerDeUtils.QUOTE)) {
            appendWithQuotes(sb, keyString);
          }
          else {
            sb.append(keyString);
          }
          sb.append(SerDeUtils.COLON);
          buildJSONString(sb, e.getValue(), mapValueObjectInspector);
        }
        sb.append(SerDeUtils.RBRACE);
      }
      break;
    }
    case STRUCT: {
      StructObjectInspector soi = (StructObjectInspector) oi;
      List<? extends StructField> structFields = soi.getAllStructFieldRefs();
      if (o == null) {
        sb.append("null");
      } else {
        sb.append(SerDeUtils.LBRACE);
        for (int i = 0; i < structFields.size(); i++) {
          if (i > 0) {
            sb.append(SerDeUtils.COMMA);
          }
          appendWithQuotes(sb, structFields.get(i).getFieldName());
          sb.append(SerDeUtils.COLON);
          buildJSONString(sb, soi.getStructFieldData(o, structFields.get(i)),
            structFields.get(i).getFieldObjectInspector());
        }
        sb.append(SerDeUtils.RBRACE);
      }
      break;
    }
    case UNION: {
      UnionObjectInspector uoi = (UnionObjectInspector) oi;
      if (o == null) {
        sb.append("null");
      } else {
        sb.append(SerDeUtils.LBRACE);
        sb.append(uoi.getTag(o));
        sb.append(SerDeUtils.COLON);
        buildJSONString(sb, uoi.getField(o),
          uoi.getObjectInspectors().get(uoi.getTag(o)));
        sb.append(SerDeUtils.RBRACE);
      }
      break;
    }
    default:
      throw new RuntimeException("Unknown type in ObjectInspector!");
    }
  }
private static void buildJSONString ( StringBuilder sb , Object o , ObjectInspector oi ) throws IOException { switch ( oi . getCategory ( ) ) { case PRIMITIVE : { PrimitiveObjectInspector poi = ( PrimitiveObjectInspector ) oi ; if ( o == null ) { sb . append ( "null" ) ; } else { switch ( poi . getPrimitiveCategory ( ) ) { case BOOLEAN : { boolean b = ( ( BooleanObjectInspector ) poi ) . get ( o ) ; sb . append ( b ? "true" : "false" ) ; break ; } case BYTE : { sb . append ( ( ( ByteObjectInspector ) poi ) . get ( o ) ) ; break ; } case SHORT : { sb . append ( ( ( ShortObjectInspector ) poi ) . get ( o ) ) ; break ; } case INT : { sb . append ( ( ( IntObjectInspector ) poi ) . get ( o ) ) ; break ; } case LONG : { sb . append ( ( ( LongObjectInspector ) poi ) . get ( o ) ) ; break ; } case FLOAT : { sb . append ( ( ( FloatObjectInspector ) poi ) . get ( o ) ) ; break ; } case DOUBLE : { sb . append ( ( ( DoubleObjectInspector ) poi ) . get ( o ) ) ; break ; } case STRING : { String s = SerDeUtils . escapeString ( ( ( StringObjectInspector ) poi ) . getPrimitiveJavaObject ( o ) ) ; appendWithQuotes ( sb , s ) ; break ; } case BINARY : { throw new IOException ( "JsonSerDe does not support BINARY type" ) ; } case DATE : Date d = ( ( DateObjectInspector ) poi ) . getPrimitiveJavaObject ( o ) ; appendWithQuotes ( sb , d . toString ( ) ) ; break ; case TIMESTAMP : { Timestamp t = ( ( TimestampObjectInspector ) poi ) . getPrimitiveJavaObject ( o ) ; appendWithQuotes ( sb , t . toString ( ) ) ; break ; } case DECIMAL : sb . append ( ( ( HiveDecimalObjectInspector ) poi ) . getPrimitiveJavaObject ( o ) ) ; break ; case VARCHAR : { String s = SerDeUtils . escapeString ( ( ( HiveVarcharObjectInspector ) poi ) . getPrimitiveJavaObject ( o ) . toString ( ) ) ; appendWithQuotes ( sb , s ) ; break ; } case CHAR : { String s = SerDeUtils . escapeString ( ( ( HiveCharObjectInspector ) poi ) . getPrimitiveJavaObject ( o ) . toString ( ) ) ; appendWithQuotes ( sb , s ) ; break ; } default : throw new RuntimeException ( "Unknown primitive type: " + poi . getPrimitiveCategory ( ) ) ; } } break ; } case LIST : { ListObjectInspector loi = ( ListObjectInspector ) oi ; ObjectInspector listElementObjectInspector = loi . getListElementObjectInspector ( ) ; List < ? > olist = loi . getList ( o ) ; if ( olist == null ) { sb . append ( "null" ) ; } else { sb . append ( SerDeUtils . LBRACKET ) ; for ( int i = 0 ; i < olist . size ( ) ; i ++ ) { if ( i > 0 ) { sb . append ( SerDeUtils . COMMA ) ; } buildJSONString ( sb , olist . get ( i ) , listElementObjectInspector ) ; } sb . append ( SerDeUtils . RBRACKET ) ; } break ; } case MAP : { MapObjectInspector moi = ( MapObjectInspector ) oi ; ObjectInspector mapKeyObjectInspector = moi . getMapKeyObjectInspector ( ) ; ObjectInspector mapValueObjectInspector = moi . getMapValueObjectInspector ( ) ; Map < ? , ? > omap = moi . getMap ( o ) ; if ( omap == null ) { sb . append ( "null" ) ; } else { sb . append ( SerDeUtils . LBRACE ) ; boolean first = true ; for ( Object entry : omap . entrySet ( ) ) { if ( first ) { first = false ; } else { sb . append ( SerDeUtils . COMMA ) ; } Map . Entry < ? , ? > e = ( Map . Entry < ? , ? > ) entry ; StringBuilder keyBuilder = new StringBuilder ( ) ; buildJSONString ( keyBuilder , e . getKey ( ) , mapKeyObjectInspector ) ; String keyString = keyBuilder . toString ( ) . trim ( ) ; if ( ( ! keyString . isEmpty ( ) ) && ( keyString . charAt ( 0 ) != SerDeUtils . QUOTE ) ) { appendWithQuotes ( sb , keyString ) ; } else { sb . append ( keyString ) ; } sb . append ( SerDeUtils . COLON ) ; buildJSONString ( sb , e . getValue ( ) , mapValueObjectInspector ) ; } sb . append ( SerDeUtils . RBRACE ) ; } break ; } case STRUCT : { StructObjectInspector soi = ( StructObjectInspector ) oi ; List < ? extends StructField > structFields = soi . getAllStructFieldRefs ( ) ; if ( o == null ) { sb . append ( "null" ) ; } else { sb . append ( SerDeUtils . LBRACE ) ; for ( int i = 0 ; i < structFields . size ( ) ; i ++ ) { if ( i > 0 ) { sb . append ( SerDeUtils . COMMA ) ; } appendWithQuotes ( sb , structFields . get ( i ) . getFieldName ( ) ) ; sb . append ( SerDeUtils . COLON ) ; buildJSONString ( sb , soi . getStructFieldData ( o , structFields . get ( i ) ) , structFields . get ( i ) . getFieldObjectInspector ( ) ) ; } sb . append ( SerDeUtils . RBRACE ) ; } break ; } case UNION : { UnionObjectInspector uoi = ( UnionObjectInspector ) oi ; if ( o == null ) { sb . append ( "null" ) ; } else { sb . append ( SerDeUtils . LBRACE ) ; sb . append ( uoi . getTag ( o ) ) ; sb . append ( SerDeUtils . COLON ) ; buildJSONString ( sb , uoi . getField ( o ) , uoi . getObjectInspectors ( ) . get ( uoi . getTag ( o ) ) ) ; sb . append ( SerDeUtils . RBRACE ) ; } break ; } default : throw new RuntimeException ( "Unknown type in ObjectInspector!" ) ; } }
Also, throws IOException when Binary is detected.