001/*
002 * Copyright 2013 Box, Inc. All rights reserved.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.nuxeo.box.api.marshalling.jsonparsing;
017
018import com.fasterxml.jackson.annotation.JsonInclude.Include;
019import com.fasterxml.jackson.core.JsonFactory;
020import com.fasterxml.jackson.core.JsonParser;
021import com.fasterxml.jackson.databind.DeserializationFeature;
022import com.fasterxml.jackson.databind.ObjectMapper;
023import com.fasterxml.jackson.databind.jsontype.NamedType;
024
025import org.nuxeo.box.api.marshalling.exceptions.BoxJSONException;
026import org.nuxeo.box.api.marshalling.interfaces.IBoxJSONParser;
027import org.nuxeo.box.api.marshalling.interfaces.IBoxResourceHub;
028import org.nuxeo.box.api.marshalling.interfaces.IBoxType;
029
030import java.io.IOException;
031import java.io.InputStream;
032
033/**
034 * The json parser class wrapping Jackson JSON parser. For now, if user wants to remove jackson dependency(jackson
035 * jars), all the overriden methods and constructor of this class needs to be rewritten against the cusomized json
036 * parser. An alternative approach (not taken yet) requires user to implement a new IBoxJSONParser, in the meantime make
037 * all the jackson library related calls in this class reflection calls. However this is error prone if we need to
038 * update jackson. Since jackson is still the recommended way. We are not doing the reflection way yet.
039 */
040public class BoxJSONParser implements IBoxJSONParser {
041
042    private final ObjectMapper mObjectMapper;
043
044    public BoxJSONParser(final IBoxResourceHub hub) {
045        mObjectMapper = new ObjectMapper();
046        mObjectMapper.setSerializationInclusion(Include.NON_NULL);
047        mObjectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
048        mObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
049        for (IBoxType type : hub.getAllTypes()) {
050            mObjectMapper.registerSubtypes(new NamedType(hub.getClass(type), type.toString()));
051        }
052    }
053
054    protected ObjectMapper getObjectMapper() {
055        return mObjectMapper;
056    }
057
058    @Override
059    public String convertBoxObjectToJSONStringQuietly(final Object object) {
060        try {
061            return convertBoxObjectToJSONString(object);
062        } catch (BoxJSONException e) {
063            return null;
064        }
065    }
066
067    @Override
068    public <T> T parseIntoBoxObjectQuietly(final InputStream inputStream, final Class<T> theClass) {
069        try {
070            return parseIntoBoxObject(inputStream, theClass);
071        } catch (BoxJSONException e) {
072            return null;
073        }
074    }
075
076    @Override
077    public <T> T parseIntoBoxObjectQuietly(final String jsonString, final Class<T> theClass) {
078        try {
079            return parseIntoBoxObject(jsonString, theClass);
080        } catch (BoxJSONException e) {
081            return null;
082        }
083    }
084
085    @Override
086    public String convertBoxObjectToJSONString(Object object) throws BoxJSONException {
087        try {
088            return getObjectMapper().writeValueAsString(object);
089        } catch (IOException e) {
090            throw new BoxJSONException(e);
091        }
092    }
093
094    @Override
095    public <T> T parseIntoBoxObject(InputStream inputStream, Class<T> theClass) throws BoxJSONException {
096        try {
097            JsonFactory jsonFactory = new JsonFactory();
098            JsonParser jp = jsonFactory.createJsonParser(inputStream);
099            return getObjectMapper().readValue(jp, theClass);
100        } catch (IOException e) {
101            throw new BoxJSONException(e);
102        }
103    }
104
105    @Override
106    public <T> T parseIntoBoxObject(String jsonString, Class<T> theClass) throws BoxJSONException {
107        try {
108            JsonFactory jsonFactory = new JsonFactory();
109            JsonParser jp = jsonFactory.createJsonParser(jsonString);
110            return getObjectMapper().readValue(jp, theClass);
111        } catch (IOException e) {
112            throw new BoxJSONException(e);
113        }
114    }
115}