microsoft-azure-storage/src/com/microsoft/azure/storage/table/TableDeserializer.java
private static <T extends TableEntity, R> TableResult parseJsonEntity(final JsonParser parser,
            final Class<T> clazzType, HashMap<String, PropertyPair> classProperties, final EntityResolver<R> resolver,
            final TableRequestOptions options, final OperationContext opContext) throws JsonParseException,
            IOException, StorageException, InstantiationException, IllegalAccessException {
        final TableResult res = new TableResult();

        final HashMap<String, EntityProperty> properties = new HashMap<String, EntityProperty>();

        if (!parser.hasCurrentToken()) {
            parser.nextToken();
        }

        JsonUtilities.assertIsStartObjectJsonToken(parser);

        parser.nextToken();

        // get all metadata, if present
        while (parser.getCurrentName().startsWith(ODataConstants.ODATA_PREFIX)) {
            final String name = parser.getCurrentName().substring(ODataConstants.ODATA_PREFIX.length());

            // get the value token
            parser.nextToken();

            if (name.equals(ODataConstants.ETAG)) {
                String etag = parser.getValueAsString();
                res.setEtag(etag);
            }

            // get the key token
            parser.nextToken();
        }

        if (resolver == null && clazzType == null) {
            return res;
        }

        // get object properties
        while (parser.getCurrentToken() != JsonToken.END_OBJECT) {
            String key = Constants.EMPTY_STRING;
            String val = Constants.EMPTY_STRING;
            EdmType edmType = null;

            // checks if this property is preceded by an OData property type annotation
            if (options.getTablePayloadFormat() != TablePayloadFormat.JsonNoMetadata
                    && parser.getCurrentName().endsWith(ODataConstants.ODATA_TYPE_SUFFIX)) {
                parser.nextToken();
                edmType = EdmType.parse(parser.getValueAsString());

                parser.nextValue();
                key = parser.getCurrentName();
                val = parser.getValueAsString();
            }
            else {
                key = parser.getCurrentName();

                parser.nextToken();
                val = parser.getValueAsString();
                edmType = evaluateEdmType(parser.getCurrentToken(), parser.getValueAsString());
            }

            final EntityProperty newProp = new EntityProperty(val, edmType);
            newProp.setDateBackwardCompatibility(options.getDateBackwardCompatibility());
            properties.put(key, newProp);

            parser.nextToken();
        }

        String partitionKey = null;
        String rowKey = null;
        Date timestamp = null;
        String etag = null;

        // Remove core properties from map and set individually
        EntityProperty tempProp = properties.remove(TableConstants.PARTITION_KEY);
        if (tempProp != null) {
            partitionKey = tempProp.getValueAsString();
        }

        tempProp = properties.remove(TableConstants.ROW_KEY);
        if (tempProp != null) {
            rowKey = tempProp.getValueAsString();
        }

        tempProp = properties.remove(TableConstants.TIMESTAMP);
        if (tempProp != null) {
            tempProp.setDateBackwardCompatibility(false);
            timestamp = tempProp.getValueAsDate();

            if (res.getEtag() == null) {
                etag = getETagFromTimestamp(tempProp.getValueAsString());
                res.setEtag(etag);
            }
        }

        // do further processing for type if JsonNoMetdata by inferring type information via resolver or clazzType
        if (options.getTablePayloadFormat() == TablePayloadFormat.JsonNoMetadata
                && (options.getPropertyResolver() != null || clazzType != null)) {
            if (options.getPropertyResolver() != null) {
                for (final Entry<String, EntityProperty> p : properties.entrySet()) {
                    final String key = p.getKey();
                    final String value = p.getValue().getValueAsString();
                    EdmType edmType;

                    // try to use the property resolver to get the type
                    try {
                        edmType = options.getPropertyResolver().propertyResolver(partitionKey, rowKey, key, value);
                    }
                    catch (Exception e) {
                        throw new StorageException(StorageErrorCodeStrings.INTERNAL_ERROR, SR.CUSTOM_RESOLVER_THREW,
                                Constants.HeaderConstants.HTTP_UNUSED_306, null, e);
                    }

                    // try to create a new entity property using the returned type
                    try {
                        final EntityProperty newProp = new EntityProperty(value, edmType);
                        newProp.setDateBackwardCompatibility(options.getDateBackwardCompatibility());
                        properties.put(p.getKey(), newProp);
                    }
                    catch (IllegalArgumentException e) {
                        throw new StorageException(StorageErrorCodeStrings.INVALID_TYPE, String.format(
                                SR.FAILED_TO_PARSE_PROPERTY, key, value, edmType),
                                Constants.HeaderConstants.HTTP_UNUSED_306, null, e);
                    }
                }
            }
            else if (clazzType != null) {
                if (classProperties == null) {
                    classProperties = PropertyPair.generatePropertyPairs(clazzType);
                }
                for (final Entry<String, EntityProperty> p : properties.entrySet()) {
                    PropertyPair propPair = classProperties.get(p.getKey());
                    if (propPair != null) {
                        final EntityProperty newProp = new EntityProperty(p.getValue().getValueAsString(),
                                propPair.type);
                        newProp.setDateBackwardCompatibility(options.getDateBackwardCompatibility());
                        properties.put(p.getKey(), newProp);
                    }
                }
            }
        }

        // set the result properties, now that they are appropriately parsed
        res.setProperties(properties);

        // use resolver if provided, else create entity based on clazz type
        if (resolver != null) {
            res.setResult(resolver.resolve(partitionKey, rowKey, timestamp, res.getProperties(), res.getEtag()));
        }
        else if (clazzType != null) {
            // Generate new entity and return
            final T entity = clazzType.newInstance();
            entity.setEtag(res.getEtag());

            entity.setPartitionKey(partitionKey);
            entity.setRowKey(rowKey);
            entity.setTimestamp(timestamp);
            
            entity.readEntity(res.getProperties(), opContext);

            res.setResult(entity);
        }

        return res;
    }
private static <T extends TableEntity, R> TableResult parseJsonEntity(final JsonParser parser,
            final Class<T> clazzType, HashMap<String, PropertyPair> classProperties, final EntityResolver<R> resolver,
            final TableRequestOptions options, final OperationContext opContext) throws JsonParseException,
            IOException, StorageException, InstantiationException, IllegalAccessException {
        final TableResult res = new TableResult();

        final HashMap<String, EntityProperty> properties = new HashMap<String, EntityProperty>();

        if (!parser.hasCurrentToken()) {
            parser.nextToken();
        }

        JsonUtilities.assertIsStartObjectJsonToken(parser);

        parser.nextToken();

        // get all metadata, if present
        while (parser.getCurrentName().startsWith(ODataConstants.ODATA_PREFIX)) {
            final String name = parser.getCurrentName().substring(ODataConstants.ODATA_PREFIX.length());

            // get the value token
            parser.nextToken();

            if (name.equals(ODataConstants.ETAG)) {
                String etag = parser.getValueAsString();
                res.setEtag(etag);
            }

            // get the key token
            parser.nextToken();
        }

        if (resolver == null && clazzType == null) {
            return res;
        }

        // get object properties
        while (parser.getCurrentToken() != JsonToken.END_OBJECT) {
            String key = Constants.EMPTY_STRING;
            String val = Constants.EMPTY_STRING;
            EdmType edmType = null;

            // checks if this property is preceded by an OData property type annotation
            if (options.getTablePayloadFormat() != TablePayloadFormat.JsonNoMetadata
                    && parser.getCurrentName().endsWith(ODataConstants.ODATA_TYPE_SUFFIX)) {
                parser.nextToken();
                edmType = EdmType.parse(parser.getValueAsString());

                parser.nextValue();
                key = parser.getCurrentName();
                val = parser.getValueAsString();
            }
            else {
                key = parser.getCurrentName();

                parser.nextToken();
                val = parser.getValueAsString();
                edmType = evaluateEdmType(parser.getCurrentToken(), parser.getValueAsString());
            }

            final EntityProperty newProp = new EntityProperty(val, edmType);
            newProp.setDateBackwardCompatibility(options.getDateBackwardCompatibility());
            properties.put(key, newProp);

            parser.nextToken();
        }

        String partitionKey = null;
        String rowKey = null;
        Date timestamp = null;
        String etag = null;

        // Remove core properties from map and set individually
        EntityProperty tempProp = properties.remove(TableConstants.PARTITION_KEY);
        if (tempProp != null) {
            partitionKey = tempProp.getValueAsString();
        }

        tempProp = properties.remove(TableConstants.ROW_KEY);
        if (tempProp != null) {
            rowKey = tempProp.getValueAsString();
        }

        tempProp = properties.remove(TableConstants.TIMESTAMP);
        if (tempProp != null) {
            tempProp.setDateBackwardCompatibility(false);
            timestamp = tempProp.getValueAsDate();

            if (res.getEtag() == null) {
                etag = getETagFromTimestamp(tempProp.getValueAsString());
                res.setEtag(etag);
            }
        }

        // do further processing for type if JsonNoMetdata by inferring type information via resolver or clazzType
        if (options.getTablePayloadFormat() == TablePayloadFormat.JsonNoMetadata
                && (options.getPropertyResolver() != null || clazzType != null)) {
            if (options.getPropertyResolver() != null) {
                for (final Entry<String, EntityProperty> p : properties.entrySet()) {
                    final String key = p.getKey();
                    final String value = p.getValue().getValueAsString();
                    EdmType edmType;

                    // try to use the property resolver to get the type
                    try {
                        edmType = options.getPropertyResolver().propertyResolver(partitionKey, rowKey, key, value);
                    }
                    catch (Exception e) {
                        throw new StorageException(StorageErrorCodeStrings.INTERNAL_ERROR, SR.CUSTOM_RESOLVER_THREW,
                                Constants.HeaderConstants.HTTP_UNUSED_306, null, e);
                    }

                    // try to create a new entity property using the returned type
                    try {
                        final EntityProperty newProp = new EntityProperty(value, edmType);
                        newProp.setDateBackwardCompatibility(options.getDateBackwardCompatibility());
                        properties.put(p.getKey(), newProp);
                    }
                    catch (IllegalArgumentException e) {
                        throw new StorageException(StorageErrorCodeStrings.INVALID_TYPE, String.format(
                                SR.FAILED_TO_PARSE_PROPERTY, key, value, edmType),
                                Constants.HeaderConstants.HTTP_UNUSED_306, null, e);
                    }
                }
            }
            else if (clazzType != null) {
                if (classProperties == null) {
                    classProperties = PropertyPair.generatePropertyPairs(clazzType);
                }
                for (final Entry<String, EntityProperty> p : properties.entrySet()) {
                    PropertyPair propPair = classProperties.get(p.getKey());
                    if (propPair != null) {
                        final EntityProperty newProp = new EntityProperty(p.getValue().getValueAsString(),
                                propPair.type);
                        newProp.setDateBackwardCompatibility(options.getDateBackwardCompatibility());
                        properties.put(p.getKey(), newProp);
                    }
                }
            }
        }

        // set the result properties, now that they are appropriately parsed
        res.setProperties(properties);

        // use resolver if provided, else create entity based on clazz type
        if (resolver != null) {
            res.setResult(resolver.resolve(partitionKey, rowKey, timestamp, res.getProperties(), res.getEtag()));
        }
        else if (clazzType != null) {
            // Generate new entity and return
            final T entity = clazzType.newInstance();
            entity.setEtag(res.getEtag());

            entity.setPartitionKey(partitionKey);
            entity.setRowKey(rowKey);
            entity.setTimestamp(timestamp);
            
            entity.readEntity(res.getProperties(), opContext);

            res.setResult(entity);
        }

        return res;
    }
Reserved for internal use. Parses the operation response as an entity. Parses the result returned in the
specified stream in JSON format into a {@link TableResult} containing an entity of the specified class type
projected using the specified resolver.

@param parser
The <code>JsonParser</code> to read the data to parse from.
@param clazzType
The class type <code>T</code> implementing {@link TableEntity} for the entity returned. Set to
<code>null</code> to ignore the returned entity and copy only response properties into the
{@link TableResult} object.
@param resolver
An {@link EntityResolver} instance to project the entity into an instance of type <code>R</code>. Set
to <code>null</code> to return the entity as an instance of the class type <code>T</code>.
@param options
A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
settings for the operation.
@param opContext
An {@link OperationContext} object used to track the execution of the operation.
@return
A {@link TableResult} containing the parsed entity result of the operation.
@throws IOException
if an error occurs while accessing the stream.
@throws InstantiationException
if an error occurs while constructing the result.
@throws IllegalAccessException
if an error occurs in reflection while parsing the result.
@throws StorageException
if a storage service error occurs.
@throws IOException
if an error occurs while accessing the stream.
@throws JsonParseException
if an error occurs while parsing the stream.