Skip to content

Adding Microsoft-style JSON Date Deserialization to as3corelib #146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 74 additions & 62 deletions src/com/adobe/serialization/json/JSONDecoder.as
Original file line number Diff line number Diff line change
@@ -32,11 +32,12 @@

package com.adobe.serialization.json
{
import com.adobe.utils.DateUtil;

public class JSONDecoder
{
/**
{

/**
* Flag indicating if the parser should be strict about the format
* of the JSON string it is attempting to decode.
*/
@@ -52,7 +53,7 @@ package com.adobe.serialization.json
private var token:JSONToken;

/**
* Constructs a new JSONDecoder to parse a JSON string
* Constructs a new JSONDecoder to parse a JSON string
* into a native object.
*
* @param s The JSON string to be converted
@@ -64,7 +65,7 @@ package com.adobe.serialization.json
* @tiptext
*/
public function JSONDecoder( s:String, strict:Boolean )
{
{
this.strict = strict;
tokenizer = new JSONTokenizer( s, strict );

@@ -97,47 +98,23 @@ package com.adobe.serialization.json
* Returns the next token from the tokenzier reading
* the JSON string
*/
private final function nextToken():JSONToken
private function nextToken():JSONToken
{
return token = tokenizer.getNextToken();
}

/**
* Returns the next token from the tokenizer reading
* the JSON string and verifies that the token is valid.
*/
private final function nextValidToken():JSONToken
{
token = tokenizer.getNextToken();
checkValidToken();

return token;
}

/**
* Verifies that the token is valid.
*/
private final function checkValidToken():void
{
// Catch errors when the input stream ends abruptly
if ( token == null )
{
tokenizer.parseError( "Unexpected end of input" );
}
}

/**
* Attempt to parse an array.
*/
private final function parseArray():Array
private function parseArray():Array
{
// create an array internally that we're going to attempt
// to parse from the tokenizer
var a:Array = new Array();

// grab the next token from the tokenizer to move
// past the opening [
nextValidToken();
nextToken();

// check to see if we have an empty array
if ( token.type == JSONTokenType.RIGHT_BRACKET )
@@ -150,12 +127,12 @@ package com.adobe.serialization.json
else if ( !strict && token.type == JSONTokenType.COMMA )
{
// move past the comma
nextValidToken();
nextToken();

// check to see if we're reached the end of the array
if ( token.type == JSONTokenType.RIGHT_BRACKET )
{
return a;
return a;
}
else
{
@@ -169,9 +146,9 @@ package com.adobe.serialization.json
{
// read in the value and add it to the array
a.push( parseValue() );

// after the value there should be a ] or a ,
nextValidToken();
nextToken();

if ( token.type == JSONTokenType.RIGHT_BRACKET )
{
@@ -187,8 +164,6 @@ package com.adobe.serialization.json
// if the decoder is not in strict mode
if ( !strict )
{
checkValidToken();

// Reached ",]" as the end of the array, so return it
if ( token.type == JSONTokenType.RIGHT_BRACKET )
{
@@ -201,25 +176,24 @@ package com.adobe.serialization.json
tokenizer.parseError( "Expecting ] or , but found " + token.value );
}
}

return null;
return null;
}

/**
* Attempt to parse an object.
*/
private final function parseObject():Object
private function parseObject():Object
{
// create the object internally that we're going to
// attempt to parse from the tokenizer
var o:Object = new Object();

// store the string part of an object member so
// that we can assign it a value in the object
var key:String

// grab the next token from the tokenizer
nextValidToken();
nextToken();

// check to see if we have an empty object
if ( token.type == JSONTokenType.RIGHT_BRACE )
@@ -232,7 +206,7 @@ package com.adobe.serialization.json
else if ( !strict && token.type == JSONTokenType.COMMA )
{
// move past the comma
nextValidToken();
nextToken();

// check to see if we're reached the end of the object
if ( token.type == JSONTokenType.RIGHT_BRACE )
@@ -255,23 +229,23 @@ package com.adobe.serialization.json
key = String( token.value );

// move past the string to see what's next
nextValidToken();
nextToken();

// after the string there should be a :
if ( token.type == JSONTokenType.COLON )
{
{
// move past the : and read/assign a value for the key
nextToken();
o[ key ] = parseValue();
o[key] = parseValue();

// move past the value to see what's next
nextValidToken();
nextToken();

// after the value there's either a } or a ,
if ( token.type == JSONTokenType.RIGHT_BRACE )
{
// we're done reading the object, so return it
return o;
return o;
}
else if ( token.type == JSONTokenType.COMMA )
{
@@ -282,8 +256,6 @@ package com.adobe.serialization.json
// if the decoder is not in strict mode
if ( !strict )
{
checkValidToken();

// Reached ",}" as the end of the object, so return it
if ( token.type == JSONTokenType.RIGHT_BRACE )
{
@@ -302,35 +274,45 @@ package com.adobe.serialization.json
}
}
else
{
{
tokenizer.parseError( "Expecting string but found " + token.value );
}
}
return null;
return null;
}

/**
* Attempt to parse a value
*/
private final function parseValue():Object
private function parseValue():Object
{
checkValidToken();

// Catch errors when the input stream ends abruptly
if ( token == null )
{
tokenizer.parseError( "Unexpected end of input" );
}

switch ( token.type )
{
case JSONTokenType.LEFT_BRACE:
return parseObject();

case JSONTokenType.LEFT_BRACKET:
return parseArray();

case JSONTokenType.STRING:
if (!isDate(token))
return token.value;

convertToDate(token);
return token.value;

case JSONTokenType.NUMBER:
case JSONTokenType.TRUE:
case JSONTokenType.FALSE:
case JSONTokenType.NULL:
return token.value;

case JSONTokenType.NAN:
if ( !strict )
{
@@ -340,13 +322,43 @@ package com.adobe.serialization.json
{
tokenizer.parseError( "Unexpected " + token.value );
}

default:
tokenizer.parseError( "Unexpected " + token.value );

}

return null;
return null;
}

/**
* Determine if the given token contains a a Date in serialized form
* @return
*/
private function isDate(token:JSONToken):Boolean
{
if (JSONTokenType.DATE == token.type)
return true;

if (DateUtil.isMicrosoftJSONDate(String(token.value)))
return true;

return false;
}

/**
* Convert the given token's type/value to Date
* @param token
*/
private function convertToDate(token:JSONToken):void
{
if (JSONTokenType.DATE == token.type)
return;

var result:Date = DateUtil.parseMicrosoftJSONDate(String(token.value));

token.value = result;
token.type = JSONTokenType.DATE;
}
}
}
138 changes: 70 additions & 68 deletions src/com/adobe/serialization/json/JSONTokenType.as
Original file line number Diff line number Diff line change
@@ -1,69 +1,71 @@
/*
Copyright (c) 2008, Adobe Systems Incorporated
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Adobe Systems Incorporated nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.adobe.serialization.json
{

/**
* Class containing constant values for the different types
* of tokens in a JSON encoded string.
*/
public final class JSONTokenType
{
public static const UNKNOWN:int = -1;

public static const COMMA:int = 0;

public static const LEFT_BRACE:int = 1;

public static const RIGHT_BRACE:int = 2;

public static const LEFT_BRACKET:int = 3;

public static const RIGHT_BRACKET:int = 4;

public static const COLON:int = 6;

public static const TRUE:int = 7;

public static const FALSE:int = 8;

public static const NULL:int = 9;

public static const STRING:int = 10;

public static const NUMBER:int = 11;

public static const NAN:int = 12;

}
/*
Copyright (c) 2008, Adobe Systems Incorporated
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Adobe Systems Incorporated nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.adobe.serialization.json {

/**
* Class containing constant values for the different types
* of tokens in a JSON encoded string.
*/
public class JSONTokenType {

public static const UNKNOWN:int = -1;

public static const COMMA:int = 0;

public static const LEFT_BRACE:int = 1;

public static const RIGHT_BRACE:int = 2;

public static const LEFT_BRACKET:int = 3;

public static const RIGHT_BRACKET:int = 4;

public static const COLON:int = 6;

public static const TRUE:int = 7;

public static const FALSE:int = 8;

public static const NULL:int = 9;

public static const STRING:int = 10;

public static const NUMBER:int = 11;

public static const NAN:int = 12;

public static const DATE:int = 13;

}

}
1,416 changes: 708 additions & 708 deletions src/com/adobe/serialization/json/JSONTokenizer.as

Large diffs are not rendered by default.

1,456 changes: 755 additions & 701 deletions src/com/adobe/utils/DateUtil.as

Large diffs are not rendered by default.