001/* 002 * Copyright 2018 the original author or authors. 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 * https://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 */ 016 017package org.springframework.batch.item.json; 018 019import java.io.IOException; 020import java.io.InputStream; 021import java.io.InputStreamReader; 022 023import com.google.gson.Gson; 024import com.google.gson.JsonIOException; 025import com.google.gson.JsonSyntaxException; 026import com.google.gson.stream.JsonReader; 027import com.google.gson.stream.JsonToken; 028 029import org.springframework.batch.item.ParseException; 030import org.springframework.core.io.Resource; 031import org.springframework.util.Assert; 032 033/** 034 * Implementation of {@link JsonObjectReader} based on 035 * <a href="https://github.com/google/gson">Google Gson</a>. 036 * 037 * @param <T> type of the target object 038 * 039 * @author Mahmoud Ben Hassine 040 * @since 4.1 041 */ 042public class GsonJsonObjectReader<T> implements JsonObjectReader<T> { 043 044 private Class<? extends T> itemType; 045 046 private JsonReader jsonReader; 047 048 private Gson mapper = new Gson(); 049 050 private InputStream inputStream; 051 052 /** 053 * Create a new {@link GsonJsonObjectReader} instance. 054 * @param itemType the target item type 055 */ 056 public GsonJsonObjectReader(Class<? extends T> itemType) { 057 this.itemType = itemType; 058 } 059 060 /** 061 * Set the object mapper to use to map Json objects to domain objects. 062 * @param mapper the object mapper to use 063 */ 064 public void setMapper(Gson mapper) { 065 Assert.notNull(mapper, "The mapper must not be null"); 066 this.mapper = mapper; 067 } 068 069 @Override 070 public void open(Resource resource) throws Exception { 071 Assert.notNull(resource, "The resource must not be null"); 072 this.inputStream = resource.getInputStream(); 073 this.jsonReader = this.mapper.newJsonReader(new InputStreamReader(this.inputStream)); 074 Assert.state(this.jsonReader.peek() == JsonToken.BEGIN_ARRAY, 075 "The Json input stream must start with an array of Json objects"); 076 this.jsonReader.beginArray(); 077 } 078 079 @Override 080 public T read() throws Exception { 081 try { 082 if (this.jsonReader.hasNext()) { 083 return this.mapper.fromJson(this.jsonReader, this.itemType); 084 } 085 } catch (IOException |JsonIOException | JsonSyntaxException e) { 086 throw new ParseException("Unable to read next JSON object", e); 087 } 088 return null; 089 } 090 091 @Override 092 public void close() throws Exception { 093 this.inputStream.close(); 094 this.jsonReader.close(); 095 } 096 097}