ListerCi
2017-12-13 16:08
采纳率: 60%
浏览 7.8k

使用Gson框架制作Json时遇到的字符转义问题

第一次做后台遇到一个Json格式的问题,刚开始得到的JsonArray格式如下:
[{"id":8,"account":"123456","password":"123456","name":"啦啦啦"},{"id":9,"account":"10086","password":"123456","name":"哈哈哈"}]
在返回给前端时需要弄成一个JsonObject,于是我写了一个实体类ReturnData,里面只有一个String data,然后使用Gson中的方法(json就是上面的jsonArray):

ReturnData returnData = new ReturnData(json);
String gsonResult = gson.toJson(returnData);

但是在转换时,Gson自动帮我添加了转义字符,最后结果如下:
{"data":"[{\"id\":8,\"account\":\"123456\",\"password\":\"123456\",\"name\":\"啦啦啦\"}
有没有大神知道为什么会自动出现这样的转义字符,以及好一点的解决办法。

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

12条回答 默认 最新

  • aaaa121s 2017-12-14 01:33
    已采纳

    将{"id":8,"account":"123456","password":"123456","name":"啦啦啦"}定义成一个对象Data,然后将这个对象数组作为ReturnData的属性===>List data;
    或者List> data;

    打赏 评论
  • Ali 2017-12-13 16:38

    说明你给 toJson发的是个字符串,gson需要把字符串转换为正常的JSON所以需要加上转义字符。

    打赏 评论
  • timezhourenquan 2017-12-13 17:18

    你定义的ReturnData只包含一个String字符串,toJson函数做的就是把这个String字符串转为json格式的,所有加上了转义字符;
    你应该把ReturnData字段定义为一个包含json结果的Java类,参考http://www.importnew.com/16638.html

    打赏 评论
  • Zhang Daopin 2017-12-14 00:47

    你可以将结果处理一下,把转义符个替换掉啊(如:.replaceAll() ),这样会比较简单一些。

    打赏 评论
  • wjz510781097 2017-12-14 01:17

    {"data":"[{\"id\":8,\"account\":\"123456\",\"password\":\"123456\",\"name\":\"啦啦啦\"}

    打赏 评论
  • qq_22464301 2017-12-14 01:21

    JSONObject message = new JSONObject(json);
    这样返回就可以了

    打赏 评论
  • zkl_asdfjkl 2017-12-14 01:25

    1.为什么会自动出现这样的转义字符? 因为字符串里有引号等等特殊字符,
    比如你要打印一个引号出来,你怎么打印呢,
    是不是这样写 String gsonResult=““”,三个引号那编译准报错,所以要加入转义符。
    2.Json解析有现成的对象。我在这边这个是c++的,应该有java版本的,你可以百度一下,或者翻译成java.
    /*
    Copyright (c) 2009 Dave Gamble

    Permission is hereby granted, dispose 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.
    example:
    string resStr;
    resStr.assign(response->getResponseData()->begin(), response->getResponseData()->end());
    Json * root = Json_create(resStr.c_str());
    if( !root)
    return;
    Json * status =Json_getItem(root,"status");
    OutputT("充值回调 status=%d", status->valueInt);
    if( status->valueInt != 0)
    return;

    */

    /* Esoteric Software: Removed everything except parsing, shorter method names, more get methods, double to float, formatted. */

    #ifndef SPINE_JSON_H_
    #define SPINE_JSON_H_

    #ifdef __cplusplus
    extern "C" {
    #endif

    /* Json Types: */
    #define Json_False 0
    #define Json_True 1
    #define Json_NULL 2
    #define Json_Number 3
    #define Json_String 4
    #define Json_Array 5
    #define Json_Object 6

    #ifndef SPINE_JSON_HAVE_PREV
    /* Spine doesn't use the "prev" link in the Json sibling lists. */
    #define SPINE_JSON_HAVE_PREV 0
    #endif

    /* The Json structure: /
    typedef struct Json {
    struct Json
    next;
    #if SPINE_JSON_HAVE_PREV
    struct Json* prev; /* next/prev allow you to walk array/object chains. Alternatively, use getSize/getItem /
    #endif
    struct Json
    child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */

    int type; /* The type of the item, as above. */
    int size; /* The number of children. */
    
    const char* valueString; /* The item's string, if type==Json_String */
    int valueInt; /* The item's number, if type==Json_Number */
    float valueFloat; /* The item's number, if type==Json_Number */
    
    const char* name; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
    

    } Json;

    /* Supply a block of JSON, and this returns a Json object you can interrogate. Call Json_dispose when finished. /
    Json
    Json_create (const char* value);

    /* Delete a Json entity and all subentities. /
    void Json_dispose (Json
    json);

    /* Get item "string" from object. Case insensitive. /
    Json
    Json_getItem (Json* json, const char* string);
    const char* Json_getString (Json* json, const char* name, const char* defaultValue);
    float Json_getFloat (Json* json, const char* name, float defaultValue);
    int Json_getInt (Json* json, const char* name, int defaultValue);

    /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. /
    const char
    Json_getError (void);

    #ifdef __cplusplus
    }
    #endif

    #endif /* SPINE_JSON_H_ */

    //----------------------------------------------------------cpp
    /*
    Copyright (c) 2009, Dave Gamble
    Copyright (c) 2013, Esoteric Software

    Permission is hereby granted, dispose 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.
    */

    /* Json /
    /
    JSON parser in C. */

    #ifndef _DEFAULT_SOURCE
    /* Bring strings.h definitions into string.h, where appropriate */
    #define _DEFAULT_SOURCE
    #endif

    #ifndef _BSD_SOURCE
    /* Bring strings.h definitions into string.h, where appropriate */
    #define _BSD_SOURCE
    #endif

    #include "Json.h"
    #include
    #include
    #include /* strtod (C89), strtof (C99) /
    #include /
    strcasecmp (4.4BSD - compatibility), _stricmp (_WIN32) */
    //#include

    #ifndef SPINE_JSON_DEBUG
    /* Define this to do extra NULL and expected-character checking */
    #define SPINE_JSON_DEBUG 0
    #endif

    static const char* ep;

    const char* Json_getError (void) {
    return ep;
    }

    static int Json_strcasecmp (const char* s1, const char* s2) {
    /* TODO we may be able to elide these NULL checks if we can prove
    * the graph and input (only callsite is Json_getItem) should not have NULLs
    /
    if (s1 && s2) {
    #if defined(_WIN32)
    return _stricmp(s1, s2);
    #else
    return strcasecmp( s1, s2 );
    #endif
    } else {
    if (s1 < s2)
    return -1; /
    s1 is null, s2 is not /
    else if (s1 == s2)
    return 0; /
    both are null /
    else
    return 1; /
    s2 is nul s1 is not */
    }
    }

    /* Internal constructor. /
    static Json *Json_new (void) {
    return (Json *)calloc(1,sizeof(Json));//return (Json
    )CALLOC(Json, 1);
    }

    /* Delete a Json structure. /
    void Json_dispose (Json *c) {
    Json *next;
    while (c) {
    next = c->next;
    if (c->child) Json_dispose(c->child);
    if (c->valueString) free((void
    )c->valueString);//FREE(c->valueString);
    if (c->name) free((void*)c->name);//FREE(c->name);
    free(c);//FREE(c);
    c = next;
    }
    }

    /* Parse the input text to generate a number, and populate the result into item. /
    static const char
    parse_number (Json item, const char num) {
    char * endptr;
    float n;

    /* Using strtod and strtof is slightly more permissive than RFC4627,
     * accepting for example hex-encoded floating point, but either
     * is often leagues faster than any manual implementation.
     *
     * We also already know that this starts with [-0-9] from parse_value.
     */
    

    #if STDC_VERSION >= 199901L
    n = strtof(num, &endptr);
    #else
    n = (float)strtod( num, &endptr );
    #endif
    /* ignore errno's ERANGE, which returns +/-HUGE_VAL /
    /
    n is 0 on any other error */

    if (endptr != num) {
        /* Parse success, number found. */
        item->valueFloat = n;
        item->valueInt = (int)n;
        item->type = Json_Number;
        return endptr;
    } else {
        /* Parse failure, ep is set. */
        ep = num;
        return 0;
    }
    

    }

    /* Parse the input text into an unescaped cstring, and populate item. /
    static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
    static const char
    parse_string (Json item, const char str) {
    const char* ptr = str + 1;
    char* ptr2;
    char* out;
    int len = 0;
    unsigned uc, uc2;
    if (*str != '\"') { /* TODO: don't need this check when called from parse_value, but do need from parse_object /
    ep = str;
    return 0;
    } /
    not a string! */

    while (*ptr != '\"' && *ptr && ++len)
        if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
    
    out=(char*)malloc(len + 1);//out = MALLOC(char, len + 1); /* The length needed for the string, roughly. */
    if (!out) return 0;
    
    ptr = str + 1;
    ptr2 = out;
    while (*ptr != '\"' && *ptr) {
        if (*ptr != '\\')
            *ptr2++ = *ptr++;
        else {
            ptr++;
            switch (*ptr) {
            case 'b':
                *ptr2++ = '\b';
                break;
            case 'f':
                *ptr2++ = '\f';
                break;
            case 'n':
                *ptr2++ = '\n';
                break;
            case 'r':
                *ptr2++ = '\r';
                break;
            case 't':
                *ptr2++ = '\t';
                break;
            case 'u': /* transcode utf16 to utf8. */
                sscanf(ptr + 1, "%4x", &uc);
                ptr += 4; /* get the unicode char. */
    
                if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) break; /* check for invalid. */
    
                /* TODO provide an option to ignore surrogates, use unicode replacement character? */
                if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs. */
                {
                    if (ptr[1] != '\\' || ptr[2] != 'u') break; /* missing second-half of surrogate.    */
                    sscanf(ptr + 3, "%4x", &uc2);
                    ptr += 6;
                    if (uc2 < 0xDC00 || uc2 > 0xDFFF) break; /* invalid second-half of surrogate.   */
                    uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
                }
    
                len = 4;
                if (uc < 0x80)
                    len = 1;
                else if (uc < 0x800)
                    len = 2;
                else if (uc < 0x10000) len = 3;
                ptr2 += len;
    
                switch (len) {
                case 4:
                    *--ptr2 = ((uc | 0x80) & 0xBF);
                    uc >>= 6;
                    /* fallthrough */
                case 3:
                    *--ptr2 = ((uc | 0x80) & 0xBF);
                    uc >>= 6;
                    /* fallthrough */
                case 2:
                    *--ptr2 = ((uc | 0x80) & 0xBF);
                    uc >>= 6;
                    /* fallthrough */
                case 1:
                    *--ptr2 = (uc | firstByteMark[len]);
                }
                ptr2 += len;
                break;
            default:
                *ptr2++ = *ptr;
                break;
            }
            ptr++;
        }
    }
    *ptr2 = 0;
    if (*ptr == '\"') ptr++; /* TODO error handling if not \" or \0 ? */
    item->valueString = out;
    item->type = Json_String;
    return ptr;
    

    }

    /* Predeclare these prototypes. /
    static const char
    parse_value (Json item, const char value);
    static const char* parse_array (Json item, const char value);
    static const char* parse_object (Json item, const char value);

    /* Utility to jump whitespace and cr/lf /
    static const char
    skip (const char* in) {
    if (!in) return 0; /* must propagate NULL since it's often called in skip(f(...)) form */
    while (*in && (unsigned char)*in <= 32)
    in++;
    return in;
    }

    /* Parse an object - create a new root, and populate. /
    Json *Json_create (const char
    value) {
    Json c;
    ep = 0;
    if (!value) return 0; /
    only place we check for NULL other than skip() /
    c = Json_new();
    if (!c) return 0; /
    memory fail */

    value = parse_value(c, skip(value));
    if (!value) {
        Json_dispose(c);
        return 0;
    } /* parse failure. ep is set. */
    
    return c;
    

    }

    /* Parser core - when encountering text, process appropriately. /
    static const char
    parse_value (Json item, const char value) {
    /* Referenced by Json_create(), parse_array(), and parse_object(). /
    /
    Always called with the result of skip(). /
    #if SPINE_JSON_DEBUG /
    Checked at entry to graph, Json_create, and after every parse_ call. /
    if (!value) return 0; /
    Fail on null. */
    #endif

    switch (*value) {
    case 'n': {
        if (!strncmp(value + 1, "ull", 3)) {
            item->type = Json_NULL;
            return value + 4;
        }
        break;
    }
    case 'f': {
        if (!strncmp(value + 1, "alse", 4)) {
            item->type = Json_False;
            /* calloc prevents us needing item->type = Json_False or valueInt = 0 here */
            return value + 5;
        }
        break;
    }
    case 't': {
        if (!strncmp(value + 1, "rue", 3)) {
            item->type = Json_True;
            item->valueInt = 1;
            return value + 4;
        }
        break;
    }
    case '\"':
        return parse_string(item, value);
    case '[':
        return parse_array(item, value);
    case '{':
        return parse_object(item, value);
    case '-': /* fallthrough */
    case '0': /* fallthrough */
    case '1': /* fallthrough */
    case '2': /* fallthrough */
    case '3': /* fallthrough */
    case '4': /* fallthrough */
    case '5': /* fallthrough */
    case '6': /* fallthrough */
    case '7': /* fallthrough */
    case '8': /* fallthrough */
    case '9':
        return parse_number(item, value);
    default:
        break;
    }
    
    ep = value;
    return 0; /* failure. */
    

    }

    /* Build an array from input text. /
    static const char
    parse_array (Json item, const char value) {
    Json *child;

    #if SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this /
    if (*value != '[') {
    ep = value;
    return 0;
    } /
    not an array! */
    #endif

    item->type = Json_Array;
    value = skip(value + 1);
    if (*value == ']') return value + 1; /* empty array. */
    
    item->child = child = Json_new();
    if (!item->child) return 0; /* memory fail */
    value = skip(parse_value(child, skip(value))); /* skip any spacing, get the value. */
    if (!value) return 0;
    item->size = 1;
    
    while (*value == ',') {
        Json *new_item = Json_new();
        if (!new_item) return 0; /* memory fail */
        child->next = new_item;
    

    #if SPINE_JSON_HAVE_PREV
    new_item->prev = child;
    #endif
    child = new_item;
    value = skip(parse_value(child, skip(value + 1)));
    if (!value) return 0; /* parse fail */
    item->size++;
    }

    if (*value == ']') return value + 1; /* end of array */
    ep = value;
    return 0; /* malformed. */
    

    }

    /* Build an object from the text. /
    static const char
    parse_object (Json item, const char value) {
    Json *child;

    #if SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this /
    if (*value != '{') {
    ep = value;
    return 0;
    } /
    not an object! */
    #endif

    item->type = Json_Object;
    value = skip(value + 1);
    if (*value == '}') return value + 1; /* empty array. */
    
    item->child = child = Json_new();
    if (!item->child) return 0;
    value = skip(parse_string(child, skip(value)));
    if (!value) return 0;
    child->name = child->valueString;
    child->valueString = 0;
    if (*value != ':') {
        ep = value;
        return 0;
    } /* fail! */
    value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
    if (!value) return 0;
    item->size = 1;
    
    while (*value == ',') {
        Json *new_item = Json_new();
        if (!new_item) return 0; /* memory fail */
        child->next = new_item;
    

    #if SPINE_JSON_HAVE_PREV
    new_item->prev = child;
    #endif
    child = new_item;
    value = skip(parse_string(child, skip(value + 1)));
    if (!value) return 0;
    child->name = child->valueString;
    child->valueString = 0;
    if (*value != ':') {
    ep = value;
    return 0;
    } /* fail! /
    value = skip(parse_value(child, skip(value + 1))); /
    skip any spacing, get the value. */
    if (!value) return 0;
    item->size++;
    }

    if (*value == '}') return value + 1; /* end of array */
    ep = value;
    return 0; /* malformed. */
    

    }

    Json Json_getItem (Json *object, const char string) {
    Json *c = object->child;
    while (c && Json_strcasecmp(c->name, string))
    c = c->next;
    return c;
    }

    const char* Json_getString (Json* object, const char* name, const char* defaultValue) {
    object = Json_getItem(object, name);
    if (object) return object->valueString;
    return defaultValue;
    }

    float Json_getFloat (Json* value, const char* name, float defaultValue) {
    value = Json_getItem(value, name);
    return value ? value->valueFloat : defaultValue;
    }

    int Json_getInt (Json* value, const char* name, int defaultValue) {
    value = Json_getItem(value, name);
    return value ? value->valueInt : defaultValue;
    }

    打赏 评论
  • nicodeme 2017-12-14 01:59

    在使用一下String result = StringEscapeUtils.unescapeJson(gsonResult );处理下

    打赏 评论
  • a986992982 2017-12-14 02:02

    具体啥原因我是不清楚,我也遇到过,跟JSONObject定义有关,使用apache 的json和googe的json有关,有的json传入前台是不带"\"的,后台json定义换一下

    打赏 评论
  • QTZ 2017-12-14 03:21

    直接将实体类ReturnData里面加属性,和json里面的一样就可以了

    打赏 评论
  • Mr丶YangZCH 2017-12-14 07:21

    转为实体类不就可以了吗

    打赏 评论
  • 小卒过河0104 2017-12-14 08:57

    试试 json.tostring

    打赏 评论

相关推荐 更多相似问题