简体   繁体   中英

Handle JSON serialization in Jboss EAP 7.2.0.GA

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:

  1. 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; } } 
  2. 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; } } 
  3. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM