• SpringBoot笔记--Jackson


        SpringUtil.getBean<GenericConversionService>().addConverter(Date2LocalDateTimeConverter())
        var handerAdapter = SpringUtil.context.getBean(RequestMappingHandlerAdapter::class.java);
    
        var listResolvers = mutableListOf<HandlerMethodArgumentResolver>()
        listResolvers.add(RequestParameterConverter(listOf(ApiParam::class.java)));
        listResolvers.addAll(handerAdapter.argumentResolvers)
    
        handerAdapter.argumentResolvers = listResolvers;
    
    internal class MyJsonMapper
    @JvmOverloads private constructor()
        : ObjectMapper() {
    
        init {
            // 设置输出时包含属性的风格
            this.findAndRegisterModules();
            this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
    
            // 允许单引号、允许不带引号的字段名称
            this.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
            this.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true)
    
            // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
            this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
            // 空值处理为空串
            this.serializerProvider.setNullValueSerializer(object : JsonSerializer<Any>() {
                @Throws(IOException::class, JsonProcessingException::class)
                override fun serialize(value: Any, jgen: JsonGenerator,
                                       provider: SerializerProvider) {
                    jgen.writeString("")
                }
            })
    
            this.registerModule(CustomModule());
    
            // 进行HTML解码。
    //        this.registerModule(SimpleModule().addSerializer(String::class.java, object : JsonSerializer<String>() {
    //            @Throws(IOException::class, JsonProcessingException::class)
    //            override fun serialize(value: String, jgen: JsonGenerator,
    //                                   provider: SerializerProvider) {
    //                jgen.writeString(StringEscapeUtils.unescapeHtml4(value))
    //            }
    //        }))
            // 设置时区
            this.setTimeZone(TimeZone.getDefault())//getTimeZone("GMT+8:00")
        }
    
    
        companion object {
    
            /**
             * 创建只输出非Null且非Empty(如List.isEmpty)的属性到Json字符串的Mapper,建议在外部接口中使用.
             */
            val instance: MyJsonMapper = MyJsonMapper();
        }
    }
    
    // 先定义一个json生成器
    class ObjectIdJsonSerializer : JsonSerializer<ObjectId>() {
        override fun serialize(o: ObjectId?, j: JsonGenerator, s: SerializerProvider) {
            if (o == null) {
                j.writeNull()
            } else {
                j.writeString(o.toString())
            }
        }
    }
    
    class LocalDateJsonSerializer : JsonSerializer<LocalDate>() {
        override fun serialize(value: LocalDate?, generator: JsonGenerator, serializers: SerializerProvider) {
            if (value == null) {
                generator.writeNull()
            } else {
                generator.writeNumber(Date.from(value.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()).time)
            }
        }
    }
    
    class LocalTimeJsonSerializer : JsonSerializer<LocalTime>() {
        override fun serialize(value: LocalTime?, generator: JsonGenerator, serializers: SerializerProvider) {
            if (value == null) {
                generator.writeNull()
            } else {
                generator.writeString(value.AsString())
            }
        }
    }
    
    class LocalDateTimeJsonSerializer : JsonSerializer<LocalDateTime>() {
        override fun serialize(value: LocalDateTime?, generator: JsonGenerator, serializers: SerializerProvider) {
            if (value == null) {
                generator.writeNull()
            } else {
                generator.writeNumber(Date.from(value.atZone(ZoneId.systemDefault()).toInstant()).time)
            }
        }
    }
    
    
    class LocalDateJsonDeserializer : JsonDeserializer<LocalDate>() {
        override fun deserialize(json: JsonParser?, ctxt: DeserializationContext?): LocalDate? {
            if (json == null) {
                return null;
            }
    
            if (json.valueAsString.contains("-")) {
                return json.valueAsString.AsLocalDateTime().toLocalDate();
            }
    
            return Date(json.longValue).AsLocalDateTime().toLocalDate();
        }
    }
    
    class LocalTimeJsonDeserializer : JsonDeserializer<LocalTime>() {
        override fun deserialize(json: JsonParser?, ctxt: DeserializationContext?): LocalTime? {
            if (json == null) {
                return null;
            }
    
            if (json.valueAsString.contains(".")) {
                return LocalTime.parse(json.valueAsString, DateTimeFormatter.ofPattern("HH:mm:ss.sss"))
            }
    
    
            return LocalTime.parse(json.valueAsString, DateTimeFormatter.ofPattern("HH:mm:ss"))
        }
    }
    
    class LocalDateTimeJsonDeserializer : JsonDeserializer<LocalDateTime>() {
        override fun deserialize(json: JsonParser?, ctxt: DeserializationContext?): LocalDateTime? {
            if (json == null) {
                return null;
            }
    
            if (json.valueAsString.contains("-")) {
                return json.valueAsString.AsLocalDateTime();
            }
    
            return Date(json.longValue).AsLocalDateTime();
        }
    }
    
    //Jackson 输出的时候,进行自定义序列化格式。
    // http://www.jianshu.com/p/a0fb6559f56d
    @Component
    class CustomModule() : SimpleModule(PackageVersion.VERSION) {
        init {
            addSerializer(ObjectId::class.java, ObjectIdJsonSerializer());
            addSerializer(LocalDate::class.java, LocalDateJsonSerializer());
            addSerializer(LocalTime::class.java, LocalTimeJsonSerializer());
            addSerializer(LocalDateTime::class.java, LocalDateTimeJsonSerializer());
    
            addDeserializer(LocalDate::class.java, LocalDateJsonDeserializer())
            addDeserializer(LocalTime::class.java, LocalTimeJsonDeserializer())
            addDeserializer(LocalDateTime::class.java, LocalDateTimeJsonDeserializer())
        }
    }
    
    fun <T> T.ToJson(): String {
        if (this is String) return this;
    
        return MyJsonMapper.instance.writeValueAsString(this) ?: ""
    }
    
    fun <T> String.FromJson(collectionClass: Class<T>): T {
        if (collectionClass == String::class.java) {
            return this as T
        }
    
        var jsonString = this.RemoveComment().Remove("
    ", "
    ")
        if (jsonString.isEmpty()) {
            return collectionClass.newInstance();
        }
    
        return MyJsonMapper.instance.readValue(jsonString, collectionClass)!!
    }
    
    inline fun <reified T> String.FromJson(): T {
        return this.FromJson(T::class.java)
    }
    
    
    class RequestParameterConverter(var canIgnoreAnnotationClazzes: List<Class<*>> = listOf()) : HandlerMethodArgumentResolver {
        override fun supportsParameter(parameter: MethodParameter?): Boolean {
    
            if (parameter == null) return false
    
            if (ServletRequest::class.java.isAssignableFrom(parameter.parameterType)) return false
            if (ServletResponse::class.java.isAssignableFrom(parameter.parameterType)) return false
            if (HttpSession::class.java.isAssignableFrom(parameter.parameterType)) return false
    
            if (parameter.hasParameterAnnotation(PathVariable::class.java)) return false;
            if (parameter.hasParameterAnnotation(CookieValue::class.java)) return false;
            if (parameter.hasParameterAnnotation(RequestHeader::class.java)) return false;
            if (parameter.hasParameterAnnotation(RequestParam::class.java)) return false;
    
            var parameterAnnotations = parameter.parameterAnnotations.toMutableList();
            parameterAnnotations.removeAll { Nullable::class.java.isInstance(it) }
            parameterAnnotations.removeAll { NotNull::class.java.isInstance(it) }
    
            canIgnoreAnnotationClazzes.forEach { ignoreClazz ->
                parameterAnnotations.removeAll { ignoreClazz.isInstance(it) }
            }
    
    
            if (parameterAnnotations.size > 0) return false;
    
            return true
            //return parameter?.hasParameterAnnotation(JsonValue::class.java) ?: false;
        }
    
        override fun resolveArgument(parameter: MethodParameter?, mavContainer: ModelAndViewContainer?, webRequest: NativeWebRequest?, binderFactory: WebDataBinderFactory?): Any? {
            if (parameter == null || mavContainer == null || webRequest == null || binderFactory == null) return null
    
            var key = parameter.parameterName
            var request = (webRequest as ServletWebRequest).request as MyHttpRequestWrapper;
            var value: Any? = null
    
            if (request.json.containsKey(key)) {
                value = request.json.get(key)
            } else if (request.requestMap.contains(key)) {
                value = request.requestMap.get(request.queryString);
            }
    
            if (value == null || (value is String && value.isEmpty())) {
                if (parameter.parameterType == String::class.java) {
                    return "";
                } else if (Number::class.java.isAssignableFrom(parameter.parameterType)) {
                    return MyUtil.getSimpleClassDefaultValue(parameter.parameterType);
                } else if (parameter.parameterType.isArray) {
                    return "[]".FromJson(parameter.parameterType)
                } else if (Iterable::class.java.isAssignableFrom(parameter.parameterType)) {
                    return "[]".FromJson(parameter.parameterType);
                }
                return null;
    //            var nullable = parameter.parameterAnnotations.any { Nullable::class.java.isInstance(it) }
    //
    //            if (nullable) {
    //                return null;
    //            }
    //            return MyUtil.getSimpleClassDefaultValue(parameter.parameterType)
            }
    
            if (parameter.parameterType.isEnum) {
                return value.AsString().ToEnum(parameter.parameterType)
            } else if (value.javaClass.isInstance(parameter.parameterType)) {
                return value;
            } else if (parameter.parameterType == Boolean::class.java) {
                return value.AsBoolean()
            } else if (parameter.parameterType == Character::class.java) {
                return value.toString()[0]
            } else if (parameter.parameterType == Byte::class.java) {
                return value.AsInt().toByte()
            } else if (parameter.parameterType == Short::class.java) {
                return value.AsInt().toShort()
            } else if (parameter.parameterType == Int::class.java ||
                    parameter.parameterType == java.lang.Integer::class.java) {
                return value.AsInt()
            } else if (parameter.parameterType == Long::class.java) {
                return value.AsLong()
            } else if (parameter.parameterType == Float::class.java) {
                return value.AsDouble()
            } else if (parameter.parameterType == Double::class.java) {
                return value.AsDouble().toLong()
            } else if (parameter.parameterType == String::class.java) {
                return value.AsString()
            } else if (parameter.parameterType == LocalDate::class.java) {
                return value.AsLocalDateTime().toLocalDate()
            } else if (parameter.parameterType == LocalTime::class.java) {
                return value.AsLocalDateTime().toLocalTime()
            } else if (parameter.parameterType == LocalDateTime::class.java) {
                return value.AsLocalDateTime()
            } else if (parameter.parameterType == Date::class.java) {
                return Date.from(value.AsLocalDateTime().atZone(ZoneId.systemDefault()).toInstant());
            } else {
                return value.AsString().FromJson(parameter.parameterType);
            }
            return value
        }
    
    }
    
    @Configuration
    open class MongoConfig {
    
        @Bean
        @Throws(Exception::class)
        open fun mongoTemplate(): MongoTemplate {
    
            var dbFactory = SpringUtil.getBean<MongoDbFactory>();
            //remove _class
            val converter = MappingMongoConverter(DefaultDbRefResolver(dbFactory), MongoMappingContext())
            converter.typeMapper = DefaultMongoTypeMapper(null)
    
            (converter.conversionService as GenericConversionService).addConverter(Date2LocalDateTimeConverter())
    
            return MongoTemplate(dbFactory, converter)
        }
    
    
    }
    
    class Date2LocalDateTimeConverter : GenericConverter {
        override fun getConvertibleTypes(): MutableSet<GenericConverter.ConvertiblePair> {
            var pairs = hashSetOf<GenericConverter.ConvertiblePair>();
            pairs.add(GenericConverter.ConvertiblePair(String::class.java, LocalDate::class.java));
            pairs.add(GenericConverter.ConvertiblePair(String::class.java, LocalTime::class.java));
            pairs.add(GenericConverter.ConvertiblePair(String::class.java, LocalDateTime::class.java));
            pairs.add(GenericConverter.ConvertiblePair(Date::class.java, LocalDate::class.java));
            pairs.add(GenericConverter.ConvertiblePair(Date::class.java, LocalTime::class.java));
            pairs.add(GenericConverter.ConvertiblePair(Date::class.java, LocalDateTime::class.java));
            pairs.add(GenericConverter.ConvertiblePair(LocalDate::class.java, Date::class.java));
            pairs.add(GenericConverter.ConvertiblePair(LocalTime::class.java, Date::class.java));
            pairs.add(GenericConverter.ConvertiblePair(LocalDateTime::class.java, Date::class.java));
            return pairs;
        }
    
        override fun convert(value: Any?, sourceType: TypeDescriptor?, targetType: TypeDescriptor?): Any? {
            if (value == null || sourceType == null || targetType == null) return null
    
            var valueClass = sourceType.type;
            var targetClass = targetType.type;
    
            if (valueClass == String::class.java) {
                var strValue = value.AsString();
                if (strValue.isEmpty()) {
                    return null;
                }
    
                if (targetClass == LocalDate::class.java) {
                    return strValue.AsLocalDateTime().toLocalDate();
                }
                if (targetClass == LocalTime::class.java) {
                    return strValue.AsLocalDateTime().toLocalTime()
                }
                if (targetClass == LocalDateTime::class.java) {
                    return strValue.AsLocalDateTime();
                }
            }
    
            if (valueClass == Date::class.java) {
                if (targetClass == LocalDate::class.java) {
                    return value.AsLocalDateTime().toLocalDate();
                }
                if (targetClass == LocalTime::class.java) {
                    return value.AsLocalDateTime().toLocalTime();
                }
                if (targetClass == LocalDateTime::class.java) {
                    return value.AsLocalDateTime()
                }
            }
    
            if (targetClass == Date::class.java) {
                if (valueClass == LocalDate::class.java) {
                    return Date.from((value as LocalDate).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
                }
                if (valueClass == LocalTime::class.java) {
                    return Date.from((value as LocalTime).atDate("1970-01-01".AsLocalDateTime().toLocalDate()).atZone(ZoneId.systemDefault()).toInstant());
                }
                if (valueClass == LocalDateTime::class.java) {
                    return Date.from((value as LocalDateTime).atZone(ZoneId.systemDefault()).toInstant());
                }
            }
    
            return null;
        }
    
    }
    

    问题

    返回实体时,如:

    • JsonTypedResult 类型, 当有消息时, 仅返回: JsonResult
    • JsonTypedResult 类型, 当 data.id 为 "000000000" 时, 返回 id= ""
  • 相关阅读:
    深入理解完美哈希
    可视化全链路日志追踪
    越界 计算机系统 栈 局部变量 类型转换
    复制状态机系统架构抽象
    C# LINQ查询将匿名类型转换成具体类型
    [ICPC 46th Shanghai] Life is a Game 克鲁斯卡尔重构树
    HBase集群搭建记录 | 云计算[CentOS7] | HBase完全分布式集群搭建
    Zookeeper集群搭建记录 | 云计算[CentOS7] | Zookeeper集群搭建
    HBase集群搭建记录 | 云计算[CentOS7] | Maven项目访问HBase
    混乱的千位符和小数点
  • 原文地址:https://www.cnblogs.com/newsea/p/7565573.html
Copyright © 2020-2023  润新知