Solving the puzzle of complex polymorphic object model deserialization in Java Jackson: Facing the JsonMappingException error – Unexpected token (START_OBJECT) instead

I am working with a hierarchy of objects described as follows:

A

B extends A

C extends B

D extends B

E extends C

F extends A and contains a reference to A

The annotation for class A is defined as:

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS,include=JsonTypeInfo.As.PROPERTY,property="@class")

When trying to deserialize a JSON array containing objects that extend class A, an error is thrown:

org.codehaus.jackson.map.JsonMappingException: Unexpected token (START_OBJECT), expected VALUE_STRING: need JSON String that contains type id (for subtype of java.util.Collection)

The JSON string is generated using the toString() method of a Set parametrized to type A. The serialization of A into JSON is achieved through the following code:

ObjectMapper objectMapper=new ObjectMapper();
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_CONCRETE_AND_ARRAYS);
        String res="";
        try {
            res = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(t);
        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return res;

The code used to deserialize the JSON array (representing the aforementioned Set) is:

ObjectMapper mapper = new ObjectMapper(); 

        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_CONCRETE_AND_ARRAYS);
        Collection<T> results=null;
        try {
            results =  mapper.readValue(json, TypeFactory.defaultInstance().constructParametricType(Collection.class, clazz ) );
        } catch (JsonParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  
        return results;

An example of the JSON format it processes looks like:

"[{
  "@class" : "pack1.pack2.MyClass",
  "id" : null,
  "f1" : "",
  "f2" : 0.9933817827,
  ...
  "featureIndicator" : false
}]"

This excerpt of JSON includes only specific objects from a sample Java Set.

Answer №1

It seems like the issue lies in the default typing setting. The JSON structure you have generated does not align with what Jackson expects when default typing is enabled. To ensure compatibility, the beginning of your JSON should look like this:

["java.util.HashSet", [{

Additionally, make sure to include an extra closing bracket }]] at the end.

The discrepancy arises from using the toString() method on your set to generate the JSON. A better approach would be to utilize the ObjectMapper class configured with default typing, as shown below:

res = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(yourSet);

Answer №2

Perhaps this solution can assist someone in a similar situation. I encountered an error caused by using the toList() method of Stream.API, which returns an immutable collection resulting in a missing ArrayList type in the final JSON object after serialization. The issue was resolved by utilizing Collectors.toList()

Before

        List<B2bItem> itemIdList = branchDto.getOrders()
            .stream()
            .map(order -> order.getItems()
                    .stream()
                    .map(OrderItemDto::getB2bItem)
                    .toList())
            .flatMap(List::stream)
            .toList(); // <---

After

        List<B2bItem> itemIdList = branchDto.getOrders()
            .stream()
            .map(order -> order.getItems()
                    .stream()
                    .map(OrderItemDto::getB2bItem)
                    .toList())
            .flatMap(List::stream)
            .collect(Collectors.toList()); // <---

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can I use conditional 'if' statements to import separate modules in Node.js ES Modules?

Recently, I tried out a tutorial that utilises CommonJS for exporting/ importing different keys depending on the environment. However, I am wondering how I can make it compatible with ES Modules import/export instead? This is the code snippet provided in ...

The Ionic search bar will only initiate a search once the keyboard is no longer in view

In my Ionic application, I have implemented a search bar to filter and search through a list. The filtering process is triggered as soon as I start typing in the search bar. However, the updated results are not displayed on the screen until I manually hide ...

Even after updating to Java 1.8 on Mac OS Yosemite, the javac compiler continues to display version 1.6

Regarding this particular question... I have encountered issues with the solutions provided. Firstly, the directory /Library/Java/Extensions is empty and the ~/Library/Java folder does not exist on my OS X Yosemite 10.10.1 system. I did perform a Java upd ...

React - the method runs correctly when triggered by state changes, but runs twice when the parent component's state changes

As I work on constructing a page that requires data to be initialized upon mounting, updated based on responses from a websocket server triggered by a button click event, and the ability to disable and re-enable the button with a countdown for the user. M ...

How to eliminate all special characters from a text in Angular

Suppose I receive a string containing special characters that needs to be transformed using filter/pipe, with the additional requirement of capitalizing the first letter of each word. For instance, transforming "@!₪ test stri&!ng₪" into "Test Stri ...

How to replicate Javascript's 32-bit signed integer arithmetic in C (or Perl) with a few differences

I have encountered a discrepancy when translating simple JS code to C and/or Perl, specifically related to arithmetic operations (+ - * / << >>) on integers causing overflow. My goal is to replicate the exact behavior of JS, including handling ...

Understanding PHP's ability to decode JSON arrays

I received this data in URL call and I am trying to extract the value of "coupon_title". Array ( [success] => 1 [data] => Array ( [0] => Array ( [0] => Array ( [featured] => [exclusive] => [promo_id] => P11757 [offer_ ...

Dealing with click events on layers with z-index positioning

In the map application I am developing, I have implemented 2 z-index layers. However, a problem arises when attempting to zoom in by clicking on these layers. The click handler is located on the lower z-index layer and I do not want it to execute when a co ...

Change the value of a particular property in an array of objects by utilizing an inline function

I am working on updating the price field for a specific object. Below is my selectedCurrenciesArray: const [selectedSwapCurrencies, setSelectedSwapCurrencies] = useState([ { symbol: null, logo: null, price: 0 }, { ...

Verification of product discount calculations using Selenium

I have a question that's been on my mind! Is there an option in Automation Testing to verify discount calculations when a product is added to the cart? Here's the scenario I'm referring to: Add a discounted product to the cart When proceed ...

Altering the state ahead of rendering

I am experiencing an issue where the Parent component is passing empty props to the Child component. This may be due to my attempt to set the state of my data within a function instead of in a constructor (for the Parent component). I only want the state o ...

Using a variable as a key for a JavaScript object literal with a string value

Is there a way to achieve this? objPrefix = btn.attr('data-objprefix'); //<button data-objPrefix="foo"> var sendData = {objPrefix : {"bar":"ccccc"}}; My desired outcome is {"foo" : {"bar":"ccccc"}}; however, the current result shows { ...

Ways to transfer information among Angular's services and components?

Exploring the Real-Time Binding of Data Between Services and Components. Consider the scenario where isAuthenticated is a public variable within an Authentication service affecting a component's view. How can one subscribe to the changes in the isAut ...

Making an HTTP request within a forEach function in Angular2

Encountering an issue while using the forEach function with HTTP requests. The _watchlistElements variable contains the following data: [{"xid":"DP_049908","name":"t10"},{"xid":"DP_928829","name":"t13"},{"xid":"DP_588690","name":"t14"},{"xid":"DP_891890" ...

What are some ways in which I can utilize the Ember Handlebars helper?

Similar Question: Using logical operators in a Handlebars.js {{#if}} statement Below is the code snippet provided: {{#each dataArray}} <li>{{#isTrue idVal1 idVal2}} display some text1 {{else}} display some text2 {{/isTrue}} & ...

Can you choose an option from a dropdown menu without relying on jQuery?

Can a dropdown list item be selected using AngularJS instead of jQuery? I have successfully accomplished this using jQuery, but I am curious if it can be done with AngularJS. This is how I achieved it using jQuery: var dropdownlist = $("select").data("k ...

Modify the CSS properties of the asp:AutoCompleteExtender using JavaScript

Is there a way to dynamically change the CompletionListItemCssClass attribute of an asp:AutoCompleteExtender using JavaScript every time the index of a combobox is changed? Here is the code snippet: ajaxtoolkit: <asp:AutoCompleteExtender ID="autocom" C ...

What is the best way to create a dynamic URL based on the choices made by a user in dynamic drop-down menus?

Utilizing JSON, I am creating a dynamic drop-down menu that consists of two lists. Additionally, there is a third drop-down list that remains static. Upon clicking the Submit button, a URL dynamically generated based on the user's selections from all ...

Retrieve a specific item from a JSON response using Node.js

When I receive a message from a WebSocket, the code snippet is triggered like this: ws.onmessage = (e) => { debugger if (e.data.startsWith('MESSAGE')) alert(JSON.stringify(e.data)) ImageReceived(e.data) c ...

Using an HTML file as the source for an image in the <img src=""> tag is a simple process that can greatly enhance the visual appeal of your webpage

My goal is to utilize an html file as the source for an image file within the <img src=""> tag in order to prevent mixed-content warnings when using an http image over https. For instance: index.html: <img src="./image.html" > image.htm ...