解决jsoncpp中文输出为unicode格式的“\u“、VS读取utf8格式中文输出乱码问题

本文介绍如何修改jsoncpp源码,使中文输出不再转为Unicode格式,同时提供VS中处理UTF8到GB2312转换的方法,确保中文字符正确显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解决jsoncpp中文输出为unicode格式的"\u"、VS读取utf8格式中文输出乱码问题

最近碰到的有一点是将后端传来的json格式数据传入C++后进行计算,再将计算结果输出为json格式返回至后端这一过程需要用到jsoncpp。

但是在jsoncpp函数输出的时候,会发现中文字符串变成了"\u"格式的一串乱码,类似这样的,然后就在网上查呀,终于发现一位博主遇到了同样的情况并给出了解决方法。嘿嘿~

https://blog.youkuaiyun.com/wgxh05/article/details/82792729超级感谢这位博主!

不过唯一不同的是我用的jsoncpp是master(1.8.4),处理方法稍微有点不一样。

1.在src\lib_json\json_writer.cpp中 找到 valueToQuotedStringN函数,这是将值输出为json格式的函数代码

static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
  if (value == NULL)
    return "";

  if (!isAnyCharRequiredQuoting(value, length))
    return JSONCPP_STRING("\"") + value + "\"";
  // We have to walk value and escape any special characters.
  // Appending to JSONCPP_STRING is not efficient, but this should be rare.
  // (Note: forward slashes are *not* rare, but I am not escaping them.)
  JSONCPP_STRING::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL
  JSONCPP_STRING result;
  result.reserve(maxsize); // to avoid lots of mallocs
  result += "\"";
  char const* end = value + length;
  for (const char* c = value; c != end; ++c) {
    switch (*c) {
    case '\"':
      result += "\\\"";
      break;
    case '\\':
      result += "\\\\";
      break;
    case '\b':
      result += "\\b";
      break;
    case '\f':
      result += "\\f";
      break;
    case '\n':
      result += "\\n";
      break;
    case '\r':
      result += "\\r";
      break;
    case '\t':
      result += "\\t";
      break;
    // case '/':
    // Even though \/ is considered a legal escape in JSON, a bare
    // slash is also legal, so I see no reason to escape it.
    // (I hope I am not misunderstanding something.)
    // blep notes: actually escaping \/ may be useful in javascript to avoid </
    // sequence.
    // Should add a flag to allow this compatibility mode and prevent this
    // sequence from occurring.
    default: {
      unsigned int cp = utf8ToCodepoint(c, end);
      // don't escape non-control characters
      // (short escape sequence are applied above)
      if (cp < 0x80 && cp >= 0x20)
        result += static_cast<char>(cp);
      else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane
        result += "\\u";
        result += toHex16Bit(cp);
      } else { // codepoint is not in Basic Multilingual Plane
               // convert to surrogate pair first
        cp -= 0x10000;
        result += "\\u";
        result += toHex16Bit((cp >> 10) + 0xD800);
        result += "\\u";
        result += toHex16Bit((cp & 0x3FF) + 0xDC00);
      }
    } break;
    }
  }
  result += "\"";
  return result;
}

其中,default就是将中文转为unicode格式字符串的代码,可以看到有一段代码是将中文转为16进制字符,为了正常输出中文,那么就需要源码这一部分改了,将

default: {
      unsigned int cp = utf8ToCodepoint(c, end);
      // don't escape non-control characters
      // (short escape sequence are applied above)
      if (cp < 0x80 && cp >= 0x20)
        result += static_cast<char>(cp);
      else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane
        result += "\\u";
        result += toHex16Bit(cp);
      } else { // codepoint is not in Basic Multilingual Plane
               // convert to surrogate pair first
        cp -= 0x10000;
        result += "\\u";
        result += toHex16Bit((cp >> 10) + 0xD800);
        result += "\\u";
        result += toHex16Bit((cp & 0x3FF) + 0xDC00);
      }
    } break;

改为

default: 
		result += *c;
		break;

直接将中文字符输出。

2.重新编译jsoncpp库,重新生成lib_json.lib

用VS打开makefiles\msvc2010\jsoncpp.sln,改好上一步之后,重新生成lib_json.lib,替换原来的lib库就好了。

3.如果发现还是有乱码问题,但不是"\u",类似这种,那是VS中遇到UTF8会自动转为ANSI格式代码,这时候需要函数转换为GB2312格式,代码如下:

string UTF8ToGB(const char* str)
{
	string result;
	WCHAR *strSrc;
	LPSTR szRes;

	int i = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
	strSrc = new WCHAR[i + 1];
	MultiByteToWideChar(CP_UTF8, 0, str, -1, strSrc, i);

	i = WideCharToMultiByte(CP_ACP, 0, strSrc, -1, NULL, 0, NULL, NULL);
	szRes = new CHAR[i + 1];
	WideCharToMultiByte(CP_ACP, 0, strSrc, -1, szRes, i, NULL, NULL);

	result = szRes;
	delete[]strSrc;
	delete[]szRes;
	return result;
}

因此在读取数据中,需要添加以上函数进行转换。

 

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值