What I am trying to do is to parse nested json data into a Java object using Gson and print it out with customized toString().
The Json Content
{"data": [
{
"symbol": "BTC",
"circulating_supply": 18975050,
"last_updated": "2022-03-05T13:54:00.000Z",
"total_supply": 18975050,
"cmc_rank": 1,
"self_reported_circulating_supply": null,
"platform": null,
"tags": [
"mineable",
"pow",
"sha-256",
"store-of-value",
"state-channel",
"coinbase-ventures-portfolio",
"three-arrows-capital-portfolio",
"polychain-capital-portfolio",
"binance-labs-portfolio",
"blockchain-capital-portfolio",
"boostvc-portfolio",
"cms-holdings-portfolio",
"dcg-portfolio",
"dragonfly-capital-portfolio",
"electric-capital-portfolio",
"fabric-ventures-portfolio",
"framework-ventures-portfolio",
"galaxy-digital-portfolio",
"huobi-capital-portfolio",
"alameda-research-portfolio",
"a16z-portfolio",
"1confirmation-portfolio",
"winklevoss-capital-portfolio",
"usv-portfolio",
"placeholder-ventures-portfolio",
"pantera-capital-portfolio",
"multicoin-capital-portfolio",
"paradigm-portfolio"
],
"date_added": "2013-04-28T00:00:00.000Z",
"quote": {"USD": {
"fully_diluted_market_cap": 820131199762.62,
"last_updated": "2022-03-05T13:54:00.000Z",
"market_cap_dominance": 42.252,
"percent_change_30d": 6.81621153,
"percent_change_1h": -0.42008562,
"percent_change_24h": -5.71623656,
"market_cap": 741049072478.8419,
"volume_change_24h": -11.0241,
"price": 39053.8666553628,
"percent_change_60d": -16.6843952,
"volume_24h": 26123993408.855915,
"percent_change_90d": -21.03603335,
"percent_change_7d": -0.10097865
}},
"num_market_pairs": 9214,
"name": "Bitcoin",
"max_supply": 21000000,
"id": 1,
"self_reported_market_cap": null,
"slug": "bitcoin"
},
{
"symbol": "ETH",
"circulating_supply": 119834013.5615,
"last_updated": "2022-03-05T13:54:00.000Z",
"total_supply": 119834013.5615,
"cmc_rank": 2,
"self_reported_circulating_supply": null,
"platform": null,
"tags": [
"mineable",
"pow",
"smart-contracts",
"ethereum-ecosystem",
"coinbase-ventures-portfolio",
"three-arrows-capital-portfolio",
"polychain-capital-portfolio",
"binance-labs-portfolio",
"blockchain-capital-portfolio",
"boostvc-portfolio",
"cms-holdings-portfolio",
"dcg-portfolio",
"dragonfly-capital-portfolio",
"electric-capital-portfolio",
"fabric-ventures-portfolio",
"framework-ventures-portfolio",
"hashkey-capital-portfolio",
"kenetic-capital-portfolio",
"huobi-capital-portfolio",
"alameda-research-portfolio",
"a16z-portfolio",
"1confirmation-portfolio",
"winklevoss-capital-portfolio",
"usv-portfolio",
"placeholder-ventures-portfolio",
"pantera-capital-portfolio",
"multicoin-capital-portfolio",
"paradigm-portfolio",
"injective-ecosystem",
"bnb-chain"
],
"date_added": "2015-08-07T00:00:00.000Z",
"quote": {"USD": {
"fully_diluted_market_cap": 316405371023.81,
"last_updated": "2022-03-05T13:54:00.000Z",
"market_cap_dominance": 18.0363,
"percent_change_30d": 1.39750424,
"percent_change_1h": -0.82066438,
"percent_change_24h": -3.20839994,
"market_cap": 316405371023.81366,
"volume_change_24h": -14.3764,
"price": 2640.363629825611,
"percent_change_60d": -31.31982292,
"volume_24h": 12406258074.91051,
"percent_change_90d": -37.45316954,
"percent_change_7d": -4.71064229
}},
"num_market_pairs": 5543,
"name": "Ethereum",
"max_supply": null,
"id": 1027,
"self_reported_market_cap": null,
"slug": "ethereum"
},
and so on...
]}
POJO Classes : Example
package controller;
import java.util.List;
import javax.annotation.processing.Generated;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
@Generated("jsonschema2pojo")
public class Example {
@SerializedName("data")
@Expose
private List<JsonFormatter> data = null;
public List<JsonFormatter> getData() {
return data;
}
public void setData(List<JsonFormatter> data) {
this.data = data;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(Example.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
sb.append("data");
sb.append('=');
sb.append(((this.data == null)?"<null>":this.data));
sb.append(',');
if (sb.charAt((sb.length()- 1)) == ',') {
sb.setCharAt((sb.length()- 1), ']');
} else {
sb.append(']');
}
return sb.toString();
}
}
POJO Classes : JsonFormatter
package controller;
import java.util.List;
import javax.annotation.processing.Generated;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
@Generated("jsonschema2pojo")
public class JsonFormatter {
@SerializedName("symbol")
@Expose
private String symbol;
@SerializedName("circulating_supply")
@Expose
private Float circulatingSupply;
@SerializedName("last_updated")
@Expose
private String lastUpdated;
@SerializedName("total_supply")
@Expose
private Float totalSupply;
@SerializedName("cmc_rank")
@Expose
private Float cmcRank;
@SerializedName("self_reported_circulating_supply")
@Expose
private Object selfReportedCirculatingSupply;
@SerializedName("platform")
@Expose
private Platform platform;
@SerializedName("tags")
@Expose
private List<String> tags = null;
@SerializedName("date_added")
@Expose
private String dateAdded;
@SerializedName("quote")
@Expose
private Quote quote;
@SerializedName("num_market_pairs")
@Expose
private Float numMarketPairs;
@SerializedName("name")
@Expose
private String name;
@SerializedName("max_supply")
@Expose
private Float maxSupply;
@SerializedName("id")
@Expose
private Integer id;
@SerializedName("self_reported_market_cap")
@Expose
private Object selfReportedMarketCap;
@SerializedName("slug")
@Expose
private String slug;
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public Float getCirculatingSupply() {
return circulatingSupply;
}
public void setCirculatingSupply(Float circulatingSupply) {
this.circulatingSupply = circulatingSupply;
}
public String getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(String lastUpdated) {
this.lastUpdated = lastUpdated;
}
public Float getTotalSupply() {
return totalSupply;
}
public void setTotalSupply(Float totalSupply) {
this.totalSupply = totalSupply;
}
public Float getCmcRank() {
return cmcRank;
}
public void setCmcRank(Float cmcRank) {
this.cmcRank = cmcRank;
}
public Object getSelfReportedCirculatingSupply() {
return selfReportedCirculatingSupply;
}
public void setSelfReportedCirculatingSupply(Object selfReportedCirculatingSupply) {
this.selfReportedCirculatingSupply = selfReportedCirculatingSupply;
}
public Platform getPlatform() {
return platform;
}
public void setPlatform(Platform platform) {
this.platform = platform;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public String getDateAdded() {
return dateAdded;
}
public void setDateAdded(String dateAdded) {
this.dateAdded = dateAdded;
}
public Quote getQuote() {
return quote;
}
public void setQuote(Quote quote) {
this.quote = quote;
}
public Float getNumMarketPairs() {
return numMarketPairs;
}
public void setNumMarketPairs(Float numMarketPairs) {
this.numMarketPairs = numMarketPairs;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getMaxSupply() {
return maxSupply;
}
public void setMaxSupply(Float maxSupply) {
this.maxSupply = maxSupply;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Object getSelfReportedMarketCap() {
return selfReportedMarketCap;
}
public void setSelfReportedMarketCap(Object selfReportedMarketCap) {
this.selfReportedMarketCap = selfReportedMarketCap;
}
public String getSlug() {
return slug;
}
public void setSlug(String slug) {
this.slug = slug;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(JsonFormatter.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
sb.append("symbol");
sb.append('=');
sb.append(((this.symbol == null)?"<null>":this.symbol));
sb.append(',');
sb.append("circulatingSupply");
sb.append('=');
sb.append(((this.circulatingSupply == null)?"<null>":this.circulatingSupply));
sb.append(',');
sb.append("lastUpdated");
sb.append('=');
sb.append(((this.lastUpdated == null)?"<null>":this.lastUpdated));
sb.append(',');
sb.append("totalSupply");
sb.append('=');
sb.append(((this.totalSupply == null)?"<null>":this.totalSupply));
sb.append(',');
sb.append("cmcRank");
sb.append('=');
sb.append(((this.cmcRank == null)?"<null>":this.cmcRank));
sb.append(',');
sb.append("selfReportedCirculatingSupply");
sb.append('=');
sb.append(((this.selfReportedCirculatingSupply == null)?"<null>":this.selfReportedCirculatingSupply));
sb.append(',');
sb.append("platform");
sb.append('=');
sb.append(((this.platform == null)?"<null>":this.platform));
sb.append(',');
sb.append("tags");
sb.append('=');
sb.append(((this.tags == null)?"<null>":this.tags));
sb.append(',');
sb.append("dateAdded");
sb.append('=');
sb.append(((this.dateAdded == null)?"<null>":this.dateAdded));
sb.append(',');
sb.append("quote");
sb.append('=');
sb.append(((this.quote == null)?"<null>":this.quote));
sb.append(',');
sb.append("numMarketPairs");
sb.append('=');
sb.append(((this.numMarketPairs == null)?"<null>":this.numMarketPairs));
sb.append(',');
sb.append("name");
sb.append('=');
sb.append(((this.name == null)?"<null>":this.name));
sb.append(',');
sb.append("maxSupply");
sb.append('=');
sb.append(((this.maxSupply == null)?"<null>":this.maxSupply));
sb.append(',');
sb.append("id");
sb.append('=');
sb.append(((this.id == null)?"<null>":this.id));
sb.append(',');
sb.append("selfReportedMarketCap");
sb.append('=');
sb.append(((this.selfReportedMarketCap == null)?"<null>":this.selfReportedMarketCap));
sb.append(',');
sb.append("slug");
sb.append('=');
sb.append(((this.slug == null)?"<null>":this.slug));
sb.append(',');
if (sb.charAt((sb.length()- 1)) == ',') {
sb.setCharAt((sb.length()- 1), ']');
} else {
sb.append(']');
}
return sb.toString();
}
}
There are also other classes for my POJO, and the way I tried to parse it into Gson is :
Gson gson = new Gson();
Type type = new TypeToken<Map<String, ArrayList<JsonFormatter>>>() {}.getType();
Map<String, ArrayList<Example>> nodeProperties = gson.fromJson(json.toString(), type);
but when I try to print out its sub values like
for (Map.Entry<String, ArrayList<Example>> set : nodeProperties.entrySet()) {
System.out.println(set.getValue().get(0).getData().get(0).toString());
}
I get the error :
class controller.JsonFormatter cannot be cast to class controller.Example (controller.JsonFormatter and controller.Example are in unnamed module of loader 'app')
What I want to achieve is to print the above json content as like this:
Symbol: BTC
Circulating_supply: 18975050
...
Tags:
mineable
Can anyone please help me out to solve this problem? Thanks in advance!
CodePudding user response:
The issue is in these lines:
Type type = new TypeToken<Map<String, ArrayList<JsonFormatter>>>() {}.getType();
Map<String, ArrayList<Example>> nodeProperties = gson.fromJson(json.toString(), type);
The TypeToken
is for Map<String, ArrayList<JsonFormatter>>
, but you store the parsed JSON in a variable of type Map<String, ArrayList<Example>>
. Unfortunately Gson.fromJson(..., Type)
does not provide any type safety guarantees, therefore you must make sure that the provided Type
matches the type of the variable you store the result in. Additionally due to Java's type erasure at runtime, you do not notice this JsonFormatter
vs. Example
mismatch until you iterate over the elements, causing the ClassCastException
.
Based on the JSON data you provided, it looks to me like you could just use gson.fromJson(json.toString(), Example.class)
, but please verify whether that is actually correct for your use case.