Jsonparseexception: Unexpected Character ('S' (Code 115)): Was Expecting Double-Quote to Start Field Name

I am trying to test my services using Junit and Mockito. I am able to mock the service and get the response from the Resource class. The response body is having some data of JSON format which is of the object type. I am trying to get the data from the object using ObjectMapper of Jackson library using spring boot.

EmployeeResource.java

package com.ems.resource;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.ems.exception.InvalidInputDataException;
import com.ems.service.EmployeeService;
import com.ems.service.UserService;
import com.ems.util.EmailUtils;
import com.ms.base.beans.EmailObject;
import com.ms.base.entity.Employee;
import com.ms.base.entity.User;

@RestController
@RequestMapping(path = "/employee")
public class EmployeeResource 
{

    final Logger logger = LogManager.getLogger(EmployeeResource.class);
    final String EMAIL_QUEUE_NAME = "EmailQueue";
            
    @Autowired
    JmsTemplate jmsTemplate;
    
    @Autowired
    EmployeeService employeeService;
    
    @Autowired 
    UserService userService;
    
    @RequestMapping(path = "/list", method = {RequestMethod.GET, RequestMethod.POST})
    @PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_HR', 'ROLE_EMP_CRUD')")
    public ResponseEntity<Object> listEmployees() throws Exception
    {
        Map responseMap = new HashMap();
        List<Employee> employees = employeeService.getEmployees();
        
        responseMap.put("employees", employees);
        responseMap.put("status", HttpStatus.OK.value());
        responseMap.put("statusName", HttpStatus.OK.name());
        
        return new ResponseEntity(responseMap, HttpStatus.OK);
    }
}

EmployeeService.java

package com.ems.service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ems.repository.EmployeeRepository;
import com.ms.base.entity.Employee;

@Service
public class EmployeeService 
{

    @Autowired
    EmployeeRepository employeeRepository;
    
    @Autowired
    UserService userService;
    
    
    public List<Employee> getEmployees()
    {
        return employeeRepository.findAll();
    }
}

EmployeeResourceTest.java

package com.ems.resource;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.ResponseEntity;

import com.ems.service.EmployeeService;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.gson.JsonObject;
import com.ms.base.entity.Employee;

@RunWith(JUnitPlatform.class)
@ExtendWith(MockitoExtension.class)
public class EmployeeResourceTest 
{

    @InjectMocks
    private EmployeeResource employeeResource;
    
    @Mock
    private EmployeeService employeeService;
    
    
    @Test 
    public void getAllEmployees() throws Exception
    {
        
        
         // given
        Employee employee1 = new Employee();
        employee1.setId(1L);
        employee1.setName("Vineel Pellella");
        employee1.setDateOfBirth(new Date(780537600));
        employee1.setDateOfJoining(new Date());
        employee1.setDesignation("ROLE_ADMIN");
        employee1.setWorkLocation("Hyderabad");
        employee1.setContactNo(9985896040L);
        employee1.setEmail("[email protected]");

        List<Employee> employees = new ArrayList<Employee>();
        employees.addAll(Arrays.asList(employee1));
 
        when(employeeService.getEmployees()).thenReturn(employees);
 
        // when
        ResponseEntity<Object> result = employeeResource.listEmployees();
        
        // then
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
        
        JsonParser parser = objectMapper.createParser(result.getBody().toString());
        
        Map respMap = objectMapper.readValue(parser, Map.class);
//        System.out.println(emp.getDateOfBirth());
        assertThat(result.getBody()).isNotNull();
        verify(employeeResource).listEmployees();
        verify(employeeService).getEmployees();
        
         
    }
    
}

Employee.java

package com.ms.base.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Data
@NoArgsConstructor
public class Employee implements Serializable
{
    private static final long serialVersionUID = -3732596549369515261L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;    
    
    private String name;
    private String designation;
    private Date dateOfBirth;
    private Date dateOfJoining;
    private String workLocation;

    @Column(unique = true)
    private Long contactNo;
    
    @Column(unique = true)
    private String email;
    private Date dateOfLeaving;
    

}

The employeeRepository is just an interface of JPARepository.

StackTrace

com.fasterxml.jackson.core.JsonParseException: Unexpected character ('s' (code 115)): was expecting double-quote to start field name
 at [Source: (String)"{statusName=OK, employees=[Employee(id=1, name=Vineel Pellella, designation=null, dateOfBirth=Sat Jan 10 06:18:57 IST 1970, dateOfJoining=Mon Sep 27 15:34:45 IST 2021, workLocation=Hyderabad, contactNo=9985896040, [email protected], dateOfLeaving=null)], status=200}"; line: 1, column: 3]
    at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2337)
    at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:710)
    at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:635)
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleOddName(ReaderBasedJsonParser.java:1814)
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextFieldName(ReaderBasedJsonParser.java:941)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:582)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:437)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:32)
    at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3548)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3516)
    at com.ems.resource.EmployeeResourceTest.getAllEmployees(EmployeeResourceTest.java:62)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.util.ArrayList.forEach(Unknown Source)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.util.ArrayList.forEach(Unknown Source)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
    at org.junit.platform.runner.JUnitPlatform.run(JUnitPlatform.java:139)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)

Result of result.getBody().toString()

{statusName=OK, employees=[Employee(id=1, name=Vineel Pellella, designation=ROLE_ADMIN, dateOfBirth=Sat Jan 10 06:18:57 IST 1970, dateOfJoining=Mon Sep 27 17:22:09 IST 2021, workLocation=Hyderabad, contactNo=9985896040, [email protected], dateOfLeaving=null), Employee(id=2, name=Vineel Pellella2, designation=ROLE_ADMIN, ROLE_HR, dateOfBirth=Sat Jan 10 06:18:57 IST 1970, dateOfJoining=Mon Sep 27 17:22:09 IST 2021, workLocation=Bengaluru, contactNo=9985896041, [email protected], dateOfLeaving=null), Employee(id=3, name=Vineel Pellella3, designation=ROLE_ADMIN, ROLE_HR, dateOfBirth=Sat Jan 10 06:18:57 IST 1970, dateOfJoining=Mon Sep 27 17:22:09 IST 2021, workLocation=Chennai, contactNo=9985896042, [email protected], dateOfLeaving=null)], status=200}
3

4 Answers

After long research, I tried the below approach which is automatically converting the invalid JSON to valid JSON.

ObjectMapper objectMapper = new ObjectMapper();
String respData = objectMapper.writeValueAsString(result.getBody());
Map respMap = objectMapper.readValue(respData, Map.class);
1

Check that you are passing valid JSON string to the parser. As mentioned in the error logs its not valid JSON, Unexpected character ('s' (code 115)): was expecting double-quote to start field name. Or you can add the flag JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES to allow un-quoted field name handling.

4

I get the same problem. The problem is that this isn't valid JSON .  JSON keys are required to be quoted strings. You must quote "statusName", "employees"... change the form until you get all the JSON keys like quoted strings .  I hope that it works, bro !

1

Please check your JSON object for missing or unmatched quotes!

2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Maya Lin-Takahashi

Maya Lin-Takahashi

Consumer Tech & Gadget Reviewer

Maya is a hardware enthusiast who tests and reviews smart home devices, smartphones, wearables, and audio gear. She focuses on practical consumer value and build quality.

Share this article
Twitter Facebook Pinterest