blob: c531449a72ddc41892242fa95526287e7e1cbd56 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.johnzon.jsonb.serializer;
import java.lang.reflect.Type;
import javax.json.JsonArrayBuilder;
import javax.json.JsonBuilderFactory;
import javax.json.JsonObjectBuilder;
import javax.json.JsonValue;
import javax.json.bind.serializer.DeserializationContext;
import javax.json.spi.JsonProvider;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParsingException;
import org.apache.johnzon.mapper.MappingParser;
public class JohnzonDeserializationContext implements DeserializationContext {
private final MappingParser runtime;
private final JsonBuilderFactory builderFactory;
private final JsonProvider jsonp;
public JohnzonDeserializationContext(final MappingParser runtime,
final JsonBuilderFactory builderFactory,
final JsonProvider jsonp) {
this.runtime = runtime;
this.builderFactory = builderFactory;
this.jsonp = jsonp;
}
@Override
public <T> T deserialize(final Class<T> clazz, final JsonParser parser) {
return runtime.readObject(read(parser), clazz);
}
@Override
public <T> T deserialize(final Type type, final JsonParser parser) {
return runtime.readObject(read(parser), type);
}
private JsonValue read(final JsonParser parser) {
final JsonParser.Event next = /*RewindableJsonParser.class.isInstance(parser) ?
RewindableJsonParser.class.cast(parser).getLast() : */ parser.next();
switch (next) {
case START_OBJECT: {
final JsonObjectBuilder objectBuilder = builderFactory.createObjectBuilder();
parseObject(null, parser, objectBuilder);
return objectBuilder.build();
}
case END_OBJECT:
return JsonValue.EMPTY_JSON_OBJECT;
case END_ARRAY:
return JsonValue.EMPTY_JSON_ARRAY;
case START_ARRAY:
final JsonArrayBuilder arrayBuilder = builderFactory.createArrayBuilder();
parseArray(parser, arrayBuilder);
return arrayBuilder.build();
case KEY_NAME: { // object
final JsonObjectBuilder objectBuilder = builderFactory.createObjectBuilder();
parseObject(parser.getString(), parser, objectBuilder);
return objectBuilder.build();
}
case VALUE_STRING:
return jsonp.createValue(parser.getString());
case VALUE_FALSE:
return JsonValue.FALSE;
case VALUE_TRUE:
return JsonValue.TRUE;
case VALUE_NULL:
return JsonValue.NULL;
case VALUE_NUMBER:
return jsonp.createValue(parser.getBigDecimal());
default:
throw new JsonParsingException("Unknown structure: " + next, parser.getLocation());
}
}
private void parseObject(final String originalKey, final JsonParser parser, final JsonObjectBuilder builder) {
String key = originalKey;
while (parser.hasNext()) {
final JsonParser.Event next = parser.next();
switch (next) {
case KEY_NAME:
key = parser.getString();
break;
case VALUE_STRING:
builder.add(key, jsonp.createValue(parser.getString()));
break;
case START_OBJECT:
final JsonObjectBuilder subObject = builderFactory.createObjectBuilder();
parseObject(null, parser, subObject);
builder.add(key, subObject);
break;
case START_ARRAY:
final JsonArrayBuilder subArray = builderFactory.createArrayBuilder();
parseArray(parser, subArray);
builder.add(key, subArray);
break;
case VALUE_NUMBER:
if (parser.isIntegralNumber()) {
builder.add(key, jsonp.createValue(parser.getLong()));
} else {
builder.add(key, jsonp.createValue(parser.getBigDecimal()));
}
break;
case VALUE_NULL:
builder.addNull(key);
break;
case VALUE_TRUE:
builder.add(key, true);
break;
case VALUE_FALSE:
builder.add(key, false);
break;
case END_OBJECT:
return;
case END_ARRAY:
throw new JsonParsingException("']', shouldn't occur", parser.getLocation());
default:
throw new JsonParsingException(next.name() + ", shouldn't occur", parser.getLocation());
}
}
}
private void parseArray(final JsonParser parser, final JsonArrayBuilder builder) {
while (parser.hasNext()) {
final JsonParser.Event next = parser.next();
switch (next) {
case VALUE_STRING:
builder.add(jsonp.createValue(parser.getString()));
break;
case VALUE_NUMBER:
if (parser.isIntegralNumber()) {
builder.add(jsonp.createValue(parser.getLong()));
} else {
builder.add(jsonp.createValue(parser.getBigDecimal()));
}
break;
case START_OBJECT:
final JsonObjectBuilder subObject = builderFactory.createObjectBuilder();
parseObject(null, parser, subObject);
builder.add(subObject);
break;
case START_ARRAY:
final JsonArrayBuilder subArray = builderFactory.createArrayBuilder();
parseArray(parser, subArray);
builder.add(subArray);
break;
case END_ARRAY:
return;
case VALUE_NULL:
builder.addNull();
break;
case VALUE_TRUE:
builder.add(true);
break;
case VALUE_FALSE:
builder.add(false);
break;
case KEY_NAME:
throw new JsonParsingException("array doesn't have keys", parser.getLocation());
case END_OBJECT:
throw new JsonParsingException("'}', shouldn't occur", parser.getLocation());
default:
throw new JsonParsingException(next.name() + ", shouldn't occur", parser.getLocation());
}
}
}
}