TestModule() { addSerializer(Interval.class, ToStringSerializer.instance); addDeserializer( Interval.class, new StdDeserializer<Interval>(Interval.class) { @Override public Interval deserialize( JsonParser jsonParser, DeserializationContext deserializationContext ) throws IOException, JsonProcessingException { return new Interval(jsonParser.getText()); } } ); }
/** * Method called by {@link com.fasterxml.jackson.databind.deser.BasicDeserializerFactory} * to register deserializers this class provides. */ // @Override public Collection<StdDeserializer<?>> provide() { return Arrays.asList(new StdDeserializer<?>[] { new DurationDeserializer() ,new GregorianCalendarDeserializer() ,new QNameDeserializer() }); }
protected CustomDeserializer(StdDeserializer<?> src) { super(src); }
@Override public void updateRegistry(TypeSpec.Builder registry, UserMarkerAnnotation annotation) { TypeName retType = annotation.getServiceInterfaceTypeName(); TypeSpec.Builder deserializerBuilder = TypeSpec.classBuilder(DESERIALIZER_CLASS) .superclass(ParameterizedTypeName.get(ClassName.get(StdDeserializer.class), retType)) .addModifiers(Modifier.PUBLIC) .addModifiers(Modifier.STATIC) .addModifiers(Modifier.FINAL) .addMethod(MethodSpec.constructorBuilder().addStatement("this(null)").build()) .addMethod(MethodSpec.constructorBuilder().addParameter(Class.class, "clazz").addStatement("super(clazz)").build()); String jsonParser = "jsonParser"; String registeredName = "registeredName"; String node = "node"; String fieldNames = "fieldNames"; MethodSpec deserializerMethod = MethodSpec.methodBuilder("deserialize") .addModifiers(Modifier.PUBLIC) .addParameter(JsonParser.class, jsonParser) .addParameter(DeserializationContext.class, "ctxt") .addException(IOException.class) .addException(JsonProcessingException.class) .returns(annotation.getServiceInterfaceTypeName()) .addStatement("$T $L", String.class, registeredName) .beginControlFlow("if ($L.isExpectedStartObjectToken())", jsonParser) .addStatement("$T $L = $L.getCodec().readTree($L)", TreeNode.class, node, jsonParser, jsonParser) // Check that object has exactly one key .addComment("Check that object has exactly one key") .addStatement("$T $L = $L.fieldNames()", ITERATOR_STRING, fieldNames, node) .beginControlFlow("if (!$L.hasNext())", fieldNames) // No keys; throw an exception .addComment("No keys; throw an exception") .addStatement(String.format("throw new RuntimeException(\"Failed to deserialize %s: no field names found\")", annotation.getServiceInterfaceName())) .endControlFlow() // At least one key; get the registered name .addComment("At least one key; get the registered name") .addStatement("$L = $L.next()", registeredName, fieldNames) .beginControlFlow("if ($L.hasNext())", fieldNames) .addComment("Too many keys; input is malformed") .addStatement(String.format("throw new RuntimeException(\"Failed to deserialize %s: too many field names found\")", annotation.getServiceInterfaceName())) .endControlFlow() .addComment("Check that service is registered and initialize") .beginControlFlow("if (getInstance().$L.containsKey($L))", "pluginMap", registeredName) .addStatement("return getInstance().$L.get($L).deserialize($L.get($L).traverse($L.getCodec()))", "pluginMap", registeredName, node, registeredName, jsonParser) .nextControlFlow("else") .addStatement(String.format("throw new RuntimeException($T.format(\"Failed to deserialize %s: Service \\\"%%s\\\" not found in registry\", $L))", annotation.getServiceInterfaceName()), String.class, registeredName) .endControlFlow() .nextControlFlow("else") .addComment("Not an object; assume we're working with a string that corresponds to a configuration-less service") .addStatement("$L = $L.getValueAsString()", registeredName, jsonParser) .addComment("Check that service is registered and initialize") .beginControlFlow("if (getInstance().$L.containsKey($L))", "pluginMap", registeredName) .addStatement("return getInstance().$L.get($L).deserialize()", "pluginMap", registeredName) .nextControlFlow("else") .addStatement(String.format("throw new RuntimeException($T.format(\"Failed to deserialize %s: Service \\\"%%s\\\" not found in registry\", $L))", annotation.getServiceInterfaceName()), String.class, registeredName) .endControlFlow() .endControlFlow() .build(); deserializerBuilder = deserializerBuilder.addMethod(deserializerMethod); TypeName configType = ParameterizedTypeName.get(ClassName.get(TypeReference.class), WildcardTypeName.subtypeOf(Object.class)); String serviceName = "serviceName"; MethodSpec getConfigTypeReference = MethodSpec.methodBuilder("getConfigTypeReference") .addModifiers(Modifier.PUBLIC) .addModifiers(Modifier.STATIC) .addParameter(String.class, serviceName) .returns(configType) .beginControlFlow("if (getInstance().$L.containsKey($L))", "pluginMap", serviceName) .addStatement("return getInstance().$L.get($L).getConfigTypeReference()", "pluginMap", serviceName) .nextControlFlow("else") .addStatement("return null") .endControlFlow() .build(); registry.addType(deserializerBuilder.build()); registry.addMethod(getConfigTypeReference); }
/** * Creates a custom Jackson deserializer for the given * {@link TypeElement}. Filling out the logic of the actual * deserialize method using the {@link DeserializerCreator * #implementDeserializeMethod(TypeElement, Builder)} * method implemented by our subclasses. * * @param typeElement The interface to create a custom deserializer for */ public void createDeserializer(TypeElement typeElement) { Name className = typeElement.getSimpleName(); DeclaredType declaredType = this.typeUtils.getDeclaredType(typeElement); ClassName stdDeserializer = ClassName.get(StdDeserializer.class); TypeName deserializerType = TypeName.get(declaredType); ParameterizedTypeName parameterizedDeserializer = ParameterizedTypeName.get(stdDeserializer, deserializerType); MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC); // since Generics don't work when calling .class, check if there are type parameters if (typeElement.getTypeParameters().isEmpty()) { // if not we can use $T constructorBuilder.addStatement("super($T.class)", typeElement); } else { // if so, we need to use the fully qualified name and $L constructorBuilder.addStatement("super($L.class)", typeElement.getQualifiedName()); } MethodSpec constructor = constructorBuilder.build(); ParameterSpec jsonParserParameter = ParameterSpec.builder(JsonParser.class, JSON_PARSER_PARAMETER_NAME) .build(); ParameterSpec deserializationContextParameter = ParameterSpec.builder(DeserializationContext.class, DESERIALIZATION_CONTEXT_PARAMETER_NAME) .build(); MethodSpec.Builder deserializeMethodBuilder = MethodSpec.methodBuilder("deserialize") .addAnnotation(Override.class) .addParameter(jsonParserParameter) .addParameter(deserializationContextParameter) .addException(ClassName.get(IOException.class)) .addException(ClassName.get(JsonProcessingException.class)) .returns(TypeName.get(declaredType)) .addModifiers(Modifier.PUBLIC); MethodSpec deserializeMethod = implementDeserializeMethod(typeElement, deserializeMethodBuilder); TypeSpec deserializationClass = TypeSpec .classBuilder(className + DESERIALIZER_CLASS_NAME_SUFFIX) .superclass(parameterizedDeserializer) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addMethod(constructor) .addMethod(deserializeMethod) .build(); PackageElement packageElement = this.elementUtils.getPackageOf(typeElement); JavaFile javaFile = JavaFile .builder(packageElement.getQualifiedName().toString(), deserializationClass) .build(); // and write that file to disc try { javaFile.writeTo(this.filer); } catch (IOException e) { this.processorUtil.error(typeElement, e.getMessage()); } }
protected Deserializer(StdDeserializer<?> src) { super(src); }
@Override public void runConversion(int numberOfAttributes, int lengthOfAttribute) { int assignmentsTotal, progress = 0; assignmentsConverted = submissionsConverted = submissionsFailed = assignmentsFailed = 0; SimpleModule module = new SimpleModule().addDeserializer(String.class, new StdDeserializer<String>(String.class) { @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { String str = StringDeserializer.instance.deserialize(p, ctxt); if (StringUtils.isBlank(str)) return null; return str; } }); // woodstox xml parser defaults we don't allow values smaller than the default if (numberOfAttributes < ReaderConfig.DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT) numberOfAttributes = ReaderConfig.DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT; if (lengthOfAttribute < ReaderConfig.DEFAULT_MAX_ATTRIBUTE_LENGTH) lengthOfAttribute = ReaderConfig.DEFAULT_MAX_ATTRIBUTE_LENGTH; log.info("<===== Assignments conversion xml parser limits: number of attributes={}, attribute size={} =====>", numberOfAttributes, lengthOfAttribute); XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory(); xmlInputFactory.setProperty(WstxInputProperties.P_MAX_ATTRIBUTES_PER_ELEMENT, numberOfAttributes); xmlInputFactory.setProperty(WstxInputProperties.P_MAX_ATTRIBUTE_SIZE, lengthOfAttribute); xmlMapper = new XmlMapper(xmlInputFactory); xmlMapper.registerModule(new Jdk8Module()); xmlMapper.registerModule(module); String configValue = "org.sakaiproject.assignment.api.model.Assignment,org.sakaiproject.assignment.api.model.AssignmentSubmission"; String currentValue = serverConfigurationService.getConfig(AssignableUUIDGenerator.HIBERNATE_ASSIGNABLE_ID_CLASSES, null); if (StringUtils.isNotBlank(currentValue)) { configValue = configValue + "," + currentValue; } ServerConfigurationService.ConfigItem configItem = BasicConfigItem.makeConfigItem( AssignableUUIDGenerator.HIBERNATE_ASSIGNABLE_ID_CLASSES, configValue, AssignmentConversionServiceImpl.class.getName(), true); serverConfigurationService.registerConfigItem(configItem); List<String> preAssignments = dataProvider.fetchAssignmentsToConvert(); List<String> postAssignments = assignmentRepository.findAllAssignmentIds(); List<String> convertAssignments = new ArrayList<>(preAssignments); convertAssignments.removeAll(postAssignments); assignmentsTotal = convertAssignments.size(); log.info("<===== Assignments pre 12 [{}] and post 12 [{}] to convert {} =====>", preAssignments.size(), postAssignments.size(), assignmentsTotal); for (String assignmentId : convertAssignments) { try { convert(assignmentId); } catch (Exception e) { log.warn("Assignment conversion exception for {}", assignmentId, e); } int percent = new Double(((assignmentsConverted + assignmentsFailed) / (double) assignmentsTotal) * 100).intValue(); if (progress != percent) { progress = percent; log.info("<===== Assignments conversion completed {}% =====>", percent); } } configItem = BasicConfigItem.makeConfigItem( AssignableUUIDGenerator.HIBERNATE_ASSIGNABLE_ID_CLASSES, StringUtils.trimToEmpty(currentValue), AssignmentConversionServiceImpl.class.getName()); serverConfigurationService.registerConfigItem(configItem); log.info("<===== Assignments converted {} =====>", assignmentsConverted); log.info("<===== Submissions converted {} =====>", submissionsConverted); log.info("<===== Assignments that failed to be converted {} =====>", assignmentsFailed); log.info("<===== Submissions that failed to be converted {} =====>", submissionsFailed); }
@Override public JsonDeserializer<?> findMapDeserializer(final MapType type, final DeserializationConfig config, BeanDescription beanDesc, final KeyDeserializer keyDeserializer, final TypeDeserializer elementTypeDeserializer, final JsonDeserializer<?> elementDeserializer) throws JsonMappingException { if (ImmutableMap.class.isAssignableFrom(type.getRawClass())) { return new StdDeserializer<Object>(type) { private static final long serialVersionUID = 1L; @Override public Object deserialize(JsonParser jp, DeserializationContext context) throws IOException { JsonToken t = jp.getCurrentToken(); if (t == JsonToken.START_OBJECT) { t = jp.nextToken(); } if (t != JsonToken.FIELD_NAME && t != JsonToken.END_OBJECT) { throw context.mappingException(type.getRawClass()); } MutableMap<Object, Object> m = Maps.mutable.of(); for (; jp.getCurrentToken() == JsonToken.FIELD_NAME; jp.nextToken()) { // Pointing to field name String fieldName = jp.getCurrentName(); Object key = (keyDeserializer == null) ? fieldName : keyDeserializer.deserializeKey(fieldName, context); t = jp.nextToken(); Object value; if (t == JsonToken.VALUE_NULL) { value = null; } else if (elementDeserializer == null) { value = jp.readValueAs(type.getContentType().getRawClass()); } else if (elementTypeDeserializer == null) { value = elementDeserializer.deserialize(jp, context); } else { value = elementDeserializer.deserializeWithType(jp, context, elementTypeDeserializer); } m.put(key, value); } return m.toImmutable(); } }; } return super.findMapDeserializer(type, config, beanDesc, keyDeserializer, elementTypeDeserializer, elementDeserializer); }
@Override public JsonDeserializer<?> findCollectionDeserializer(final CollectionType type, final DeserializationConfig config, final BeanDescription beanDesc, final TypeDeserializer elementTypeDeserializer, final JsonDeserializer<?> elementDeserializer) throws JsonMappingException { if (ImmutableSet.class.isAssignableFrom(type.getRawClass())) { return new StdDeserializer<Object>(type) { private static final long serialVersionUID = 1L; @Override public Object deserialize(JsonParser jp, DeserializationContext context) throws IOException { if (jp.isExpectedStartArrayToken()) { JsonToken t; MutableSet<Object> s = Sets.mutable.of(); while ((t = jp.nextToken()) != JsonToken.END_ARRAY) { Object value; if (t == JsonToken.VALUE_NULL) { value = null; } else if (elementDeserializer == null) { value = jp.readValueAs(type.getContentType().getRawClass()); } else if (elementTypeDeserializer == null) { value = elementDeserializer.deserialize(jp, context); } else { value = elementDeserializer.deserializeWithType(jp, context, elementTypeDeserializer); } s.add(value); } return s.toImmutable(); } throw context.mappingException(type.getRawClass()); } }; } return super.findCollectionDeserializer(type, config, beanDesc, elementTypeDeserializer, elementDeserializer); }