Is there any way to force Gson to ignore any sort of parsing exception (just skip that field ) ?
Depending on the field you are looking for, you COULD just not serialize that object. For example:
public class test{
String somString;
Map<String,String> thisValueThrowsTheError;
Int somInt;
}
If you wanted to just IGNORE the Map object, you could do that like this:
public class test{
String somString;
#SerializeName("NOTAVALIDJSONOBJECTNAME")
Map<String,String> thisValueThrowsTheError;
Int somInt;
}
Gson won't see a name for that Map and it will skip that object.
Alternately (and ultimately the better solution) is just use a Deserializer to fix the issue that you have correctly. See this post as an example of a deserializer:
Gson deserialization - Trying to parse a JSON to an Object
Related
I am new to Springboot reactive
I was asked to call the following endpoint and return todays weather data only:
https://api.weather.gov/gridpoints/MLB/33,70/forecast
I believe I need to use something like this...
WebClient.create().get()
.uri("https://api.weather.gov/gridpoints/MLB/33,70/forecast")
.retrieve()
.bodyToMono(WeatherClass.class)
.block();
Do I need to map out an entire java object to match the JSON at the endpoint? is there an easy way to perhaps just grab the a certain piece of the JSON?
How would I handle something like the #context annotation in the JSON.
The WebClient in spring boot automatically uses Jackson's ObjectMapper to unmarshall json to a java object when the content type of the response is application/json. So there is no need to pull in any additional libraries or have to write any specific unmarshalling code, unless you want to use an alternate json-to-java library.
When using Jackson, you don't need to map every field in the json to your java object. You can annotate your java class with #JsonIgnoreProperties to inform jackson to ignore any properties that may appear in the json but do not have a matching field in your java object.
An example WeatherClass in which you want only the #context and forecastGenerator unmarshalled would look something like this
#JsonIgnoreProperties
public class WeatherClass {
private final List<Object> context;
private final WeatherProperties weatherProperties;
public WeatherClass(#JsonProperty("#context") List<Object> context,
#JsonProperty("properties") WeatherProperties weatherProperties) {
this.context = context;
this.weatherProperties = weatherProperties;
}
private class WeatherProperties {
private final String forecastGenerator;
private WeatherProperties(#JsonProperty("forecastGenerator") String forecastGenerator) {
this.forecastGenerator = forecastGenerator;
}
}
}
Note
#context seems to be an array that can contain multiple types (both objects and strings in your example). I've used Object to work around this but obviously isn't the most graceful solution but should be adequate to demonstrate how Jackson works
Alternatively, you can unmarshall the response to a JsonNode, which you can then use to traverse the structure of the json without converting it to a java object. For example
String forecastGenerator = WebClient.create().get()
.uri("https://api.weather.gov/gridpoints/MLB/33,70/forecast")
.retrieve()
.bodyToMono(JsonNode.class)
.block().get("properties").get("forecastGenerator").toString()
There are many other annotations provided by Jackson that can used to define how the unmarshaller functions. Too many to cover here. See Jackson Deserialisation Annotations
I am working with Jersey Web services (2.23) and use POJO mapping for the JSON-to-Object mapping (Jersey-media-moxy). I created a class as follows:
public class DataPush {
public String asset;
public String timestamp;
public Map<String,String> aspects;
}
I expected that instances of this object have the following structure:
{"asset":"abc","timestamp":"xxx","aspects":[{"key":"sdfasd","value":"sdfsd"},{"key":"sdddfasd","value":"sdfddsd"}]}
Indeed, a further element "entry" is generated:
{"asset":"sdf","timestamp":"sdfsd","aspects":{"entry":[{"key":"sdfasd","value":"sdfsd"},{"key":"sdddfasd","value":"sdfddsd"}]}}
What is the most easiest way to get rid of the "entries" element?
I know I could write my own mapping, however I hope that there is a easy solution to manage this..
You can go to topic :
Jackson JSON – Converting JSON to Map on journaldev.com.
https://www.journaldev.com/2324/jackson-json-java-parser-api-example-tutorial
I've seen examples on SO of excluding fields from serialization at runtime. I need to do that, but I'd like to have Gson handle serialization of all the fields not being excluded.
The complicating part is that I can't have Gson do the serialization first, then have a TypeAdapter modify the result. I need to somehow do the exclusion first, then have what remains be serialized. Is this even possible?
Ok, with some experimentation, and this helpful post, I was able to cobble together a way to conditionally exclude mocked fields.
The reason I'm going to all this trouble is that out-of-the-box Gson throws an exception when it encounters Spock-mocked fields.
For Spock, my check to determine if a field is mocked is to see if the class name of the value it references contains the substring EnhancerByCGLib.
Below, ResizingArrayQueueOfStrings.arrayFactory is the field that may, or may not, be mocked.
Thankfully, I can use a single JsonSerializer for all classes that need this sort of treatment. Ideally, I wouldn't have to register the serializer for every class that might be mocked... but that's a battle for another day.
The resulting JSON, when the field is mocked and ResizingArrayQueueOfStrings is serialized, is
queue {
"arrayFactory": "** mocked **",
}
otherwise, it's
queue {
"arrayFactory": {},
}
Hope this helps others with a similar need.
public class MockSerializer implements JsonSerializer<Object> {
#Override
public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) {
Gson gson = new Gson();
String className = src.getClass().getName();
boolean isMocked = className.contains("EnhancerByCGLIB");
if (isMocked) return new JsonPrimitive("** mocked **");
else return gson.toJsonTree(src);
}
}
public class ResizingArrayQueueOfStrings {
private ArrayFactory arrayFactory;
public String toString() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(ArrayFactory.class, new MockSerializer())
.setPrettyPrinting()
.create();
return gson.toJson(this);
}
}
I'm using RestTemplate.getForObject() to retrieve json that includes a couple of objects and arrays, I only want to convert one of the objects inside this json to a POJO, I don't care about the other objects inside this json.
What is the proper way to approach this?
Edit:
Another approach from accepted answer, we can use jacksons ObjectMapper
#Autowired
private ObjectMapper jacksonObjectMapper;
then
LinkedHashMap obj1 = restTemplate.getForObject(uri, LinkedHashMap.class, params);
LinkedHashMap obj2 = (LinkedHashMap)test.get("flightStatuses");
Flight flight = jacksonObjectMapper.convertValue(obj2, Flight.class);
You get the idea, just get a generic datatype from your json structure then use ObjectMapper to convert it to the class you need.
One solution would be to create a wrapper class, which includes the POJO you want to deserialize and ignore all other properties using #JsonIgnoreProperties. You would then retrieve the wrapper object and get the POJO from it.
#JsonIgnoreProperties(ignoreUnknown=true)
public class Wrapper {
private MyPojo myPojo;
}
MyPojo myPojo = restTemplate.getForObject("url", Wrapper.class).getMyPojo();
To convert a POJO to BSON with Jackson I know bson4jackson (http://www.michel-kraemer.com/binary-json-with-bson4jackson). Is there an equivalent with Google GSON?
Thanks in advance.
Check this question
I have used gson as such:
convert to pojo:
Gson gsonObj= new Gson();
MyPojo mypojoObj = gsonObj.fromJson( someJsonString, MyPojo.class);
then convert to json string:
String s=gsonObj.toJson(mypojoObj);
Also there should be a 1-1 correspondence of all parameters' names in MyPojo and the json string. You can test it out. I believeOnly those that match are serialized.
for example if:
class MyPojo
{
public String xString;
public String yString;
...
}
then with:
MyPojor= gsonObj.fromJson("{\"xString\":\"1\",\"yString\":\"1\",\"zString\":\"1\"}", MyPojor.class);
return gsonObj.toJson(r);
you get:
{"xString":"1","yString":"1"}
you can test the case where a parameter is not requested for serialization.