JsonLineMapper Example

In this post under Spring Batch, I will explain the purpose of JsonLineMapper with an example.

JsonLineMapper is used with reader bean for reading file containing JSON input as shown below

JsonFileInput.txt

{“id”:”id0″,”name”:”name0″,”status”:”status0″,”salary”:0}
{“id”:”id1″,”name”:”name1″,”status”:”status1″,”salary”:1}
{“id”:”id2″,”name”:”name2″,”status”:”status2″,”salary”:2}
{“id”:”id3″,”name”:”name3″,”status”:”status3″,”salary”:3}
{“id”:”id4″,”name”:”name4″,”status”:”status4″,”salary”:4}
{“id”:”id5″,”name”:”name5″,”status”:”status5″,”salary”:5}
{“id”:”id6″,”name”:”name6″,”status”:”status6″,”salary”:6}
{“id”:”id7″,”name”:”name7″,”status”:”status7″,”salary”:7}
{“id”:”id8″,”name”:”name8″,”status”:”status8″,”salary”:8}
{“id”:”id9″,”name”:”name9″,”status”:”status9″,”salary”:9}

Each line in the file is interpreted as a JSON object by JsonLineMapper. So each line must start with “{” and end with “}”.

JsonLineMapper converts each record to a map. For example the below record
{“id”:”id0″,”name”:”name0″,”status”:”status0″,”salary”:0}

will be converted to a map with key and value as shown below

Key –> Value
—- —–
“id” –> “id0”
“name” –> “name0”
“status” –> “status0”
“salary” –> 0

To convert each record to an Java object, we need to create a wrapper class that first delegates to JsonLineMapper to convert each record to a Map. Once that is done, the wrapper class has to convert each map to desired java object.

For our example which involves reading each record and converting to Employee object, we will create a wrapper class named JsonLineMapperWrapper as shown below

JsonLineMapperWrapper


1  package package19;
2  
3  import java.math.BigDecimal;
4  import java.util.Map;
5  
6  import org.springframework.batch.item.file.LineMapper;
7  import org.springframework.batch.item.file.mapping.JsonLineMapper;
8  
9  public class JsonLineMapperWrapper implements LineMapper{
10  private JsonLineMapper delegate;
11  
12  @Override
13  public Employee mapLine(String line, int lineNumber) throws Exception {
14      Map employeeMap = delegate.mapLine(line, lineNumber);
15      Employee employee = new Employee();
16      employee.setId((String)employeeMap.get("id"));
17      employee.setName((String)employeeMap.get("name"));
18      employee.setSalary(new BigDecimal((Integer)employeeMap.get("salary")));
19      employee.setStatus((String)employeeMap.get("status"));
20      return employee;
21  }
22 
23  public JsonLineMapper getDelegate() {
24      return delegate;
25  }
26 
27  public void setDelegate(JsonLineMapper delegate) {
28      this.delegate = delegate;
29  }
30 }

This wrapper class delegates the conversion of each record to map object to JsonLineMapper instance. Refer to line 14.

Once the map is obtained the wrapper creates an employee object from it. Refer to line 15 to 19.

Next we will show how to integrate with reader bean. Below is the xml configuration


1   <bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
2       <property name="resource" value="file:JsonFileInput.txt"/>
3       <property name="lineMapper">
4           <bean class="package19.JsonLineMapperWrapper">
5               <property name="delegate">
6                   <bean class="org.springframework.batch.item.file.mapping.JsonLineMapper"/>
7               </property>
8           </bean>
9       </property> 
10  </bean>

In the above xml, at line 4 we integrate JsonLineMapperWrapper class to our reader bean.

At line 5 to 7, we integrate Spring provided JsonLineMapper class to our JsonLineMapperWrapper bean definition.

In this way we can configure the reader to read JSON data.

Below is the complete xml configuration for your reference


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:batch="http://www.springframework.org/schema/batch"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd">
    
    <bean id="employee" class="package19.Employee" scope="prototype"/>
    
    <bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
        <property name="resource" value="file:JsonFileInput1.txt"/>
        <property name="lineMapper">
            <bean class="package19.JsonLineMapperWrapper">
                <property name="delegate">
                    <bean class="org.springframework.batch.item.file.mapping.JsonLineMapper"/>
                </property>
            </bean>
        </property> 
    </bean>
    
    <bean id="writer" class="org.springframework.batch.item.file.FlatFileItemWriter">
        <property name="resource" value="file:FileOutput.txt"/>
        <property name="lineAggregator">
            <bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
                <property name="fieldExtractor">
                    <bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
                        <property name="names" value="id,name,status,salary"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
    
    <batch:job id="importEmployees" job-repository="jobRepository">
        <batch:step id="readWriteEmployees">
            <batch:tasklet>
                <batch:chunk reader="reader" writer="writer" commit-interval="50"/>
            </batch:tasklet>
        </batch:step>
    </batch:job>
    
    <bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
    
    <bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
        <property name="transactionManager" ref="transactionManager"/>
    </bean>
    
    <bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
        <property name="jobRepository" ref="jobRepository"/>
    </bean>
</beans>

Leave a Reply