Added features that allow the reader to accept common non-standard JSON.

This is a version of patch #17, from Clay Wood:

    http://sourceforge.net/p/jsoncpp/patches/17/
This commit is contained in:
Aaron Jacobs 2014-04-23 23:28:23 +00:00
parent 77cd83890d
commit 642befc836
3 changed files with 67 additions and 11 deletions

View File

@ -42,6 +42,12 @@ namespace Json {
/// \c true if root must be either an array or an object value. Default: \c false.
bool strictRoot_;
/// \c true if dropped null placeholders are allowed. Default: \c false.
bool allowDroppedNullPlaceholders_;
/// \c true if numeric object key are allowed. Default: \c false.
bool allowNumericKeys_;
};
} // namespace Json

View File

@ -146,9 +146,11 @@ namespace Json {
bool readObject( Token &token );
bool readArray( Token &token );
bool decodeNumber( Token &token );
bool decodeNumber( Token &token, Value &decoded );
bool decodeString( Token &token );
bool decodeString( Token &token, std::string &decoded );
bool decodeDouble( Token &token );
bool decodeDouble( Token &token, Value &decoded );
bool decodeUnicodeCodePoint( Token &token,
Location &current,
Location end,

View File

@ -28,6 +28,8 @@ namespace Json {
Features::Features()
: allowComments_( true )
, strictRoot_( false )
, allowDroppedNullPlaceholders_ ( false )
, allowNumericKeys_ ( false )
{
}
@ -45,6 +47,8 @@ Features::strictMode()
Features features;
features.allowComments_ = false;
features.strictRoot_ = true;
features.allowDroppedNullPlaceholders_ = false;
features.allowNumericKeys_ = false;
return features;
}
@ -230,6 +234,16 @@ Reader::readValue()
case tokenNull:
currentValue() = Value();
break;
case tokenArraySeparator:
if ( features_.allowDroppedNullPlaceholders_ )
{
// "Un-read" the current token and mark the current value as a null
// token.
current_--;
currentValue() = Value();
break;
}
// Else, fall through...
default:
return addError( "Syntax error: value, object or array expected.", token );
}
@ -493,12 +507,24 @@ Reader::readObject( Token &/*tokenStart*/ )
break;
if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object
return true;
if ( tokenName.type_ != tokenString )
break;
name = "";
if ( !decodeString( tokenName, name ) )
return recoverFromError( tokenObjectEnd );
if ( tokenName.type_ == tokenString )
{
if ( !decodeString( tokenName, name ) )
return recoverFromError( tokenObjectEnd );
}
else if ( tokenName.type_ == tokenNumber &&
features_.allowNumericKeys_ )
{
Value numberName;
if ( !decodeNumber( tokenName, numberName ) )
return recoverFromError( tokenObjectEnd );
name = numberName.asString();
}
else
{
break;
}
Token colon;
if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator )
@ -582,6 +608,17 @@ Reader::readArray( Token &/*tokenStart*/ )
bool
Reader::decodeNumber( Token &token )
{
Value decoded;
if ( !decodeNumber( token, decoded ) )
return false;
currentValue() = decoded;
return true;
}
bool
Reader::decodeNumber( Token &token, Value &decoded )
{
bool isDouble = false;
for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
@ -591,7 +628,7 @@ Reader::decodeNumber( Token &token )
|| ( *inspect == '-' && inspect != token.start_ );
}
if ( isDouble )
return decodeDouble( token );
return decodeDouble( token, decoded );
// Attempts to parse the number as an integer. If the number is
// larger than the maximum supported value of an integer then
// we decode the number as a double.
@ -619,23 +656,34 @@ Reader::decodeNumber( Token &token )
current != token.end_ ||
digit > maxIntegerValue % 10)
{
return decodeDouble( token );
return decodeDouble( token, decoded );
}
}
value = value * 10 + digit;
}
if ( isNegative )
currentValue() = -Value::LargestInt( value );
decoded = -Value::LargestInt( value );
else if ( value <= Value::LargestUInt(Value::maxInt) )
currentValue() = Value::LargestInt( value );
decoded = Value::LargestInt( value );
else
currentValue() = value;
decoded = value;
return true;
}
bool
Reader::decodeDouble( Token &token )
{
Value decoded;
if ( !decodeDouble( token, decoded ) )
return false;
currentValue() = decoded;
return true;
}
bool
Reader::decodeDouble( Token &token, Value &decoded )
{
double value = 0;
const int bufferSize = 32;
@ -669,7 +717,7 @@ Reader::decodeDouble( Token &token )
if ( count != 1 )
return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
currentValue() = value;
decoded = value;
return true;
}