edbond
edbond

Reputation: 3951

Jackson: parsing array of arrays

I need to parse array of arrays. Here is my current code:

package android.app;

import android.support.annotation.Nullable;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.type.TypeFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 */
public class ChartData {
    private static final String MSFT_JSON = "[[\"2015-05-27\",47.61,27335600]]";
    private static final ObjectMapper mapper = new ObjectMapper();

    @Nullable
    public static ChartList msftPrice() {
        try {
            ChartList[] chartList = mapper.readValue(MSFT_JSON, ChartList[].class);
            // ChartEntry[] chartEntries = mapper.convertValue(MSFT_JSON, ChartEntry[].class);
            return null;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @JsonDeserialize(using = ChartEntryDeserializer.class)
    public static class ChartEntry {
        public String date;
        public Float price;
        public Integer volume;

        public ChartEntry(String date, Float price, Integer volume) {
            this.date = date;
            this.price = price;
            this.volume = volume;
        }
    }

    private static class ChartEntryDeserializer extends JsonDeserializer<ChartEntry> {
        public ChartEntryDeserializer() {
        }

        @Override @JsonCreator
        public ChartEntry deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            String date = p.getCodec().readValue(p, String.class);
            Float price = p.getCodec().readValue(p, Float.class);
            Integer volume = p.getCodec().readValue(p, Integer.class);

            return new ChartEntry(date, price, volume);
        }
    }

    @JsonDeserialize(using=ChartListDeserializer.class)
    public static class ChartList {
        public ChartEntry[] chartEntries;
    }

    private static class ChartListDeserializer extends JsonDeserializer<ChartList> {
        @Override
        public ChartList deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            ChartList result = new ChartList();
            result.chartEntries = p.readValuesAs(ChartEntry[].class).next();
            return result;
        }
    }
}

It does returns something like

chartList array of type ChartList [
  0: { chartEntries: [ChartEntry object]
]

how can I make it more flatten to be like:

chartList: [ array of chartEntries ]

?

Upvotes: 0

Views: 1046

Answers (1)

pards
pards

Reputation: 1166

First, you should separate your data model from your usage code. I've done this below in a JUnit test to demonstrate the usage. The data model is split into two separate classes: ChartList and ChartEntry.

The resulting JSON string looks like this:

{"chartList":[{"date":"2015-05-27","price":47.61,"volume":27335600},{"date":"2015-05-28","price":47.71,"volume":27335700}]}

Here's the test class

import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.fasterxml.jackson.databind.ObjectMapper;

public class TestClass {

    private static final ObjectMapper mapper = new ObjectMapper();

    @Test
    public void testObjToJson() throws Exception {
        ChartList list = new ChartList();
        list.addEntry(new ChartEntry("2015-05-27", 47.61f, 27335600));
        list.addEntry(new ChartEntry("2015-05-28", 47.71f, 27335700));
        System.out.println( mapper.writeValueAsString(list));
    }

    @Test
    public void testJsonToObj() throws Exception {
        final String JSON = "{\"chartList\":[{\"date\":\"2015-05-27\",\"price\":47.61,\"volume\":27335600},{\"date\":\"2015-05-28\",\"price\":47.71,\"volume\":27335700}]}";
        ChartList list = mapper.readValue(JSON, ChartList.class);
        assertEquals( 2, list.getChartList().size());
    }
}

The ChartList looks like this

import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnore;

public class ChartList {

    private List<ChartEntry> chartList = new ArrayList<>();

    @JsonIgnore
    public void addEntry(ChartEntry entry) {
        chartList.add(entry);
    }

    public List<ChartEntry> getChartList() {
        return chartList;
    }

    public void setChartList(List<ChartEntry> chartList) {
        this.chartList = chartList;
    }
}

The ChartEntry looks like this

public class ChartEntry {

    private String date;
    private Float price;
    private Integer volume;

    public ChartEntry() {
        // Needed for JSON-to-Object parsing
    }

    public ChartEntry(String date, Float price, Integer volume) {
        this.date = date;
        this.price = price;
        this.volume = volume;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        this.price = price;
    }

    public Integer getVolume() {
        return volume;
    }

    public void setVolume(Integer volume) {
        this.volume = volume;
    }
}

Upvotes: 1

Related Questions