All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.stjs.server.json.jackson.JSArrayDeserializer Maven / Gradle / Ivy

/**
 *  Copyright 2011 Alexandru Craciun, Eyal Kaspi
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.stjs.server.json.jackson;

import java.io.IOException;

import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import org.codehaus.jackson.map.TypeDeserializer;
import org.codehaus.jackson.map.deser.ContainerDeserializer;
import org.codehaus.jackson.type.JavaType;
import org.stjs.javascript.Array;
import org.stjs.javascript.JSCollections;

public class JSArrayDeserializer extends ContainerDeserializer> {

	// // Configuration

	protected final JavaType _collectionType;

	/**
	 * Value deserializer.
	 */
	final JsonDeserializer _valueDeserializer;

	/**
	 * If element instances have polymorphic type information, this is the type deserializer that can handle it
	 */
	final TypeDeserializer _valueTypeDeserializer;

	public JSArrayDeserializer(JavaType collectionType, JsonDeserializer valueDeser,
			TypeDeserializer valueTypeDeser) {
		super(collectionType.getRawClass());
		_collectionType = collectionType;
		_valueDeserializer = valueDeser;
		_valueTypeDeserializer = valueTypeDeser;
	}

	/*
	 * /********************************************************** /* ContainerDeserializer API
	 * /**********************************************************
	 */

	@Override
	public JavaType getContentType() {
		return _collectionType.getContentType();
	}

	@Override
	public JsonDeserializer getContentDeserializer() {
		return _valueDeserializer;
	}

	/*
	 * /********************************************************** /* JsonDeserializer API
	 * /**********************************************************
	 */

	@Override
	public Array deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
			JsonProcessingException {
		Array result = JSCollections.$array();

		return deserialize(jp, ctxt, result);
	}

	@Override
	public Array deserialize(JsonParser jp, DeserializationContext ctxt, Array result)
			throws IOException, JsonProcessingException {
		// Ok: must point to START_ARRAY (or equivalent)
		if (!jp.isExpectedStartArrayToken()) {
			return handleNonArray(jp, ctxt, result);
		}

		JsonDeserializer valueDes = _valueDeserializer;
		JsonToken t;
		final TypeDeserializer typeDeser = _valueTypeDeserializer;

		while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
			Object value;

			if (t == JsonToken.VALUE_NULL) {
				value = null;
			} else if (typeDeser == null) {
				value = valueDes.deserialize(jp, ctxt);
			} else {
				value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
			}
			result.push(value);
		}
		return result;
	}

	@Override
	public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer)
			throws IOException, JsonProcessingException {
		// In future could check current token... for now this should be enough:
		return typeDeserializer.deserializeTypedFromArray(jp, ctxt);
	}

	/**
	 * Helper method called when current token is no START_ARRAY. Will either throw an exception, or try to handle value
	 * as if member of implicit array, depending on configuration.
	 */
	private final Array handleNonArray(JsonParser jp, DeserializationContext ctxt, Array result)
			throws IOException, JsonProcessingException {
		// [JACKSON-526]: implicit arrays from single values?
		if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) {
			throw ctxt.mappingException(_collectionType.getRawClass());
		}
		JsonDeserializer valueDes = _valueDeserializer;
		final TypeDeserializer typeDeser = _valueTypeDeserializer;
		JsonToken t = jp.getCurrentToken();

		Object value;

		if (t == JsonToken.VALUE_NULL) {
			value = null;
		} else if (typeDeser == null) {
			value = valueDes.deserialize(jp, ctxt);
		} else {
			value = valueDes.deserializeWithType(jp, ctxt, typeDeser);
		}
		result.push(value);
		return result;
	}
}