Overview
Features
Download
Documentation
Community
Add-Ons & Services

json parser can not parse unicode string like 01\u5b57

A general discussion forum.

json parser can not parse unicode string like 01\u5b57

Postby tolauyoume » 20 Dec 2012, 22:09

when I use json parser to parse a string like:
Code: Select all
{"tid":"1","nid":"1","name":"01\u5b57\u6709\u201c\u51fa\u8eab\u201d"}

And, I found it is wrong..it this a bug?

so I compared the code with jsoncpp library, then I rewrite the (StringToken::finish) function to fix it.

Code: Select all
class StringToken: public Token
{
public:
   StringToken()
   {
   }

   virtual ~StringToken()
   {
   }

   Class tokenClass() const
   {
      return Token::STRING_LITERAL_TOKEN;
   }

   bool start(char c, std::istream& istr)
   {
      if ( c == '"')
      {
         _value = ""; // We don't need the quote!
         return true;
      }
      else return false;
   }

   void finish(std::istream& istr)
   {
      int c = istr.get();
      while (c != -1)
      {
         if ( c == 0 )
         {
            throw JSONException("Null byte not allowed");
         }

         if ( 0 < c && c <= 0x1F )
         {
            throw JSONException(format("Control character 0x%x not allowed", (unsigned int) c));
         }

         if ( c == '"' )
            break;

         if ( c == '\\' ) // Escaped String
         {
            c = istr.get();
            switch(c)
            {
            case '"' :
               _value += '"';
               break;
            case '\\' :
               _value += '\\';
               break;
            case '/' :
               _value += '/';
               break;
            case 'b' :
               _value += '\b';
               break;
            case 'f' :
               _value += '\f';
               break;
            case 'n' :
               _value += '\n';
               break;
            case 'r' :
               _value += '\r';
               break;
            case 't' :
               _value += '\t';
               break;
            case 'u' : // Unicode
            {
               Poco::Int32 unicode = decodeUnicode(istr);
               if ( unicode == 0 )
               {
                  throw JSONException("\\u0000 is not allowed");
               }
               if ( unicode >= 0xD800 && unicode <= 0xDBFF )
               {
                  c = istr.get();
                  if ( c != '\\' )
                  {
                     throw JSONException("Invalid unicode surrogate pair");
                  }
                  c = istr.get();
                  if ( c != 'u' )
                  {
                     throw JSONException("Invalid unicode surrogate pair");
                  }
                  Poco::Int32 surrogatePair = decodeUnicode(istr);
                  if ( 0xDC00 <= surrogatePair && surrogatePair <= 0xDFFF )
                  {
                     unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
                  }
                  else
                  {
                     throw JSONException("Invalid unicode surrogate pair");
                  }
               }
               else if ( 0xDC00 <= unicode && unicode <= 0xDFFF )
               {
                  throw JSONException("Invalid unicode");
               }
               //unicode to utf8
               std::string utf8;
               UnicodeConverter::toUTF8((const UTF32Char*)&unicode,1,utf8);
               //c = unicode;
               _value += utf8;

               break;
            }
            default:
            {
               throw JSONException(format("Invalid escape '%c' character used", (char) c));
            }
            }
         }else{
            _value += c;
         }
         //_value += c;
         c = istr.get();
      }

      if ( c == -1 )
      {
         throw JSONException("Unterminated string found");
      }
   }

   Poco::Int32 decodeUnicode(std::istream& istr)
   {
      Poco::Int32 value = 0;

      for(int i = 0; i < 4; i++)
      {
         value <<= 4;
         int nc = istr.peek();
         if ( nc == -1 )
         {
            throw JSONException("Invalid unicode sequence");
         }
         istr.get(); // No EOF, so read the character

         if (nc >= '0' && nc <= '9')
            value += nc - '0';
         else if (nc >= 'A' && nc <= 'F')
            value += 10 + nc - 'A';
         else if (nc >= 'a' && nc <= 'f')
            value += 10 + nc - 'a';
         else
            throw JSONException("Invalid unicode sequence. Hexadecimal digit expected");
      }

      return value;
   }
};
tolauyoume
 
Posts: 1
Joined: 20 Dec 2012, 21:52

Re: json parser can not parse unicode string like 01\u5b57

Postby Hitnrun » 28 Dec 2012, 14:44

I'm having the same problem, in your change you added the "UnicodeConverter::toUTF8((const UTF32Char*)&unicode,1,utf8);" code and commented some others, it that it?
Hitnrun
 
Posts: 20
Joined: 01 Apr 2009, 18:32

Re: json parser can not parse unicode string like 01\u5b57

Postby Hitnrun » 28 Dec 2012, 15:33

This change fixed my problem, tolauyoume would you mind making a patch of it, or can I make one based on your changes?
Hitnrun
 
Posts: 20
Joined: 01 Apr 2009, 18:32

Re: json parser can not parse unicode string like 01\u5b57

Postby Hitnrun » 29 Dec 2012, 01:23

I posted a pull request for this change:

https://github.com/pocoproject/poco/pull/45
Hitnrun
 
Posts: 20
Joined: 01 Apr 2009, 18:32

Re: json parser can not parse unicode string like 01\u5b57

Postby fbraem » 30 Dec 2012, 17:59

tolauyoume wrote:when I use json parser to parse a string like:
Code: Select all
{"tid":"1","nid":"1","name":"01\u5b57\u6709\u201c\u51fa\u8eab\u201d"}



must be written in C/C++ as:

Code: Select all
{"tid":"1","nid":"1","name":"01\\u5b57\\u6709\\u201c\\u51fa\\u8eab\\u201d"}


When only one \ is used, you use \u and the C/C++ compiler will convert it. Here we need JSON escaped unicode, so we need a double \.
Zumuta!, that's the way to do IT!
fbraem
 
Posts: 95
Joined: 11 Aug 2008, 22:47
Location: Belgium

Re: json parser can not parse unicode string like 01\u5b57

Postby alex » 05 Jan 2013, 21:00

This issue has been reviewed and aligned with jansson. See this commit in the develop branch; it will be in 1.5.1 release.
alex
 
Posts: 1044
Joined: 11 Jul 2006, 16:27
Location: United_States


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 1 guest

cron