In my Jboss, I try to implement a REST service using JAX-RS. It should return the JSON serialized version of some object
@GET
@Produces({ MediaType.APPLICATION_JSON })
public BlacklistDTO getByName(
@QueryParam("gav") final List<String> gavStringList)
{
...
}
Some parts of the object are not correctly serialized (the result is empty). How can I handle/customize the way JSON is generated by Jboss?
You can customize the configuration of your utility to serialize / deserialize JSON (usually Jackson that is included in EAP) and configure / register modules to Jackson that indicate how to perform this work on complex objects.
If you are using CDI + Resteasy + Jackson you can do:
Provide a JAX-RS Custom Json Provider where you can configure your Jackson ObjectMapper with your custom configuration.. eg.
@Provider @Produces(MediaType.APPLICATION_JSON) public class CustomJsonProvider implements ContextResolver<ObjectMapper> { private final ObjectMapper mapper; public CustomJsonProvider() { ObjectMapper mapperCdi = null; //if you are using CDI and you have your own Custom Object Mapper... BeanManager bm = CDI.current().getBeanManager(); Set<Bean<?>> sBeans = bm.getBeans(ObjectMapper.class); if (sBeans != null && !sBeans.isEmpty()) { @SuppressWarnings("unchecked") Bean<ObjectMapper> bean = (Bean<ObjectMapper>) sBeans.iterator().next(); CreationalContext<ObjectMapper> ctx = bm.createCreationalContext(bean); mapperCdi = (ObjectMapper) bm.getReference(bean, ObjectMapper.class, ctx); } if (mapperCdi != null) { mapper = mapperCdi; }else { //if you are not using CDI, you can create your own Custom Object Mapper or get it from a factory eg you can do here AppConfig.getObjectMapperInstance() or create a new one mapper = new ObjectMapper(); //eg. configuration of Hibernate 5 - Jackson Module Hibernate5Module h5m = new Hibernate5Module(); h5m.configure(Hibernate5Module.Feature.SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS, true); mapper.registerModule((com.fasterxml.jackson.databind.Module) h5m); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true); mapper.setSerializationInclusion(Include.NON_NULL); //eg. custom Jackson SimpleModule registration SimpleModule module = new SimpleModule("PaginationModule") { private static final long serialVersionUID = 1L; @Override public void setupModule(SetupContext context) { context.addAbstractTypeResolver( new SimpleAbstractTypeResolver().addMapping(Slice.class, SliceClientImpl.class)); context.addAbstractTypeResolver( new SimpleAbstractTypeResolver().addMapping(Page.class, PageClientImpl.class)); } }; mapper.registerModule(module); } } @Override public ObjectMapper getContext(Class<?> objectType) { return mapper; } }
If you are using CDI define your 'producer' method (@Produce) and your Jackson ObjectMapper factory:
@ApplicationScoped public class AppConfig { private static ObjectMapper objectMapper; // Jackson Object Mapper @Produces public ObjectMapper createMapper() { return AppConfig.getObjectMapperInstance(); } public static ObjectMapper getObjectMapperInstance() { if (objectMapper == null) { objectMapper = new ObjectMapper(); //eg. configuration of Hibernate 5 - Jackson Module //Hibernate5Module h5m = new Hibernate5Module(); //h5m.configure(Hibernate5Module.Feature.SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS, true); //objectMapper.registerModule((com.fasterxml.jackson.databind.Module) h5m); //eg. configuration of Joda - Jackson Module objectMapper.registerModule(new JodaModule()); objectMapper.setTimeZone(TimeZone.getDefault()); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); objectMapper.setSerializationInclusion(Include.NON_NULL); //eg. custom Jackson SimpleModule registration SimpleModule module = new SimpleModule("PaginationModule") { private static final long serialVersionUID = 1L; @Override public void setupModule(SetupContext context) { context.addAbstractTypeResolver( new SimpleAbstractTypeResolver().addMapping(Slice.class, SliceClientImpl.class)); context.addAbstractTypeResolver( new SimpleAbstractTypeResolver().addMapping(Page.class, PageClientImpl.class)); } }; objectMapper.registerModule(module); } return objectMapper; } }
Check that your provider is registered by Jax-rs / Resteasy:
In case your jackson configuration is not registered, try adding the following lines to your context in your web.xml:
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>your.package.CustomJsonProvider</param-value>
</context-param>
Sometimes, is required to configure as a Service Provider, adding a file "META-INF/services/javax.ws.rs.ext.Providers" (or in WEB-INF depending on the type of packaging you use war, ear, jar, etc.) with this content:
your.package.CustomJsonProvider
In another way, you can return a String (or a Response object), inject your ObjectMapper (or your utility to handle JSON format) in your Service and create/serialize your object previous the return statement.
eg. using Json-b
@Path("/myservice")
public class MyService {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Path("/resources")
public Response createJson(@FormParam("name") String name, @FormParam("surname") String surname) {
Response response;
User u = new User(name, surname);
Jsonb jsonb = JsonbBuilder.create();
String jsonString = jsonb.toJson(u);
response = Response.ok(jsonString).build();
return response;
}
}
eg. using json-b to create a custom json programmatically
// Create Json and serialize
JsonObject json = Json.createObjectBuilder()
.add("name", "Falco")
.add("age", BigDecimal.valueOf(3))
.add("biteable", Boolean.FALSE).build(); String result = json.toString();
eg. using Jackson to create a custom json programmatically
ObjectMapper mapper = new ObjectMapper();
ArrayNode arrayNode = mapper.createArrayNode();
ObjectNode objectNode1 = mapper.createObjectNode();
objectNode1.put("name", "Anna");
objectNode1.put("surname", "T");
arrayNode.add(objectNode1);
ObjectNode objectNode2 = mapper.createObjectNode();
objectNode2.put("name", "John");
objectNode2.put("surname", "X");
arrayNode.add(objectNode2);
String json = arrayNode.toString();
Hope it helps.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.