You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/08/01 09:53:40 UTC
[incubator-servicecomb-java-chassis] 04/06: [SCB-777] set custom
deserializer for Part
This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
commit 5c2aa29dd3125611e0f7a1914ac94b902050113a
Author: yaohaishi <ya...@huawei.com>
AuthorDate: Sat Jul 28 15:49:01 2018 +0800
[SCB-777] set custom deserializer for Part
---
.../foundation/common/utils/JsonUtils.java | 29 ++--
.../utils/json/JavaxServletPartDeserializer.java | 34 +++++
.../utils/json/JavaxServletPartSerializer.java | 50 +++++++
.../producer/ProducerBeanParamMapperTest.java | 146 +++++++++++++++++++++
4 files changed, 248 insertions(+), 11 deletions(-)
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java
index 75c7b36..52f9aa5 100644
--- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java
@@ -21,14 +21,18 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.core.JsonParseException;
+import javax.servlet.http.Part;
+
+import org.apache.servicecomb.foundation.common.utils.json.JavaxServletPartDeserializer;
+import org.apache.servicecomb.foundation.common.utils.json.JavaxServletPartSerializer;
+
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.module.SimpleModule;
public final class JsonUtils {
public static final ObjectMapper OBJ_MAPPER;
@@ -37,23 +41,27 @@ public final class JsonUtils {
OBJ_MAPPER = new ObjectMapper();
OBJ_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
OBJ_MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
+
+ SimpleModule partDeserializeModule = new SimpleModule("partDeserializeModule",
+ new Version(0, 0, 1, null, "javax.servlet", "javax.servlet-api")
+ );
+ partDeserializeModule.addSerializer(Part.class, new JavaxServletPartSerializer());
+ partDeserializeModule.addDeserializer(Part.class, new JavaxServletPartDeserializer());
+ OBJ_MAPPER.registerModule(partDeserializeModule);
}
private JsonUtils() {
}
- public static <T> T readValue(byte[] src,
- Class<T> valueType) throws JsonParseException, JsonMappingException, IOException {
+ public static <T> T readValue(byte[] src, Class<T> valueType) throws IOException {
return OBJ_MAPPER.readValue(src, valueType);
}
- public static <T> T readValue(InputStream is,
- Class<T> valueType) throws JsonParseException, JsonMappingException, IOException {
+ public static <T> T readValue(InputStream is, Class<T> valueType) throws IOException {
return OBJ_MAPPER.readValue(is, valueType);
}
- public static <T> T readValue(InputStream is,
- JavaType valueType) throws JsonParseException, JsonMappingException, IOException {
+ public static <T> T readValue(InputStream is, JavaType valueType) throws IOException {
return OBJ_MAPPER.readValue(is, valueType);
}
@@ -69,8 +77,7 @@ public final class JsonUtils {
return OBJ_MAPPER.convertValue(fromValue, toValueType);
}
- public static void writeValue(OutputStream out,
- Object value) throws JsonGenerationException, JsonMappingException, IOException {
+ public static void writeValue(OutputStream out, Object value) throws IOException {
OBJ_MAPPER.writeValue(out, value);
}
}
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartDeserializer.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartDeserializer.java
new file mode 100644
index 0000000..98b489f
--- /dev/null
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartDeserializer.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.foundation.common.utils.json;
+
+import java.io.IOException;
+
+import javax.servlet.http.Part;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+
+public class JavaxServletPartDeserializer extends JsonDeserializer<Part> {
+ @Override
+ public Part deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+ final Object currentValue = p.getEmbeddedObject();
+ return (Part) currentValue;
+ }
+}
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartSerializer.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartSerializer.java
new file mode 100644
index 0000000..34d247e
--- /dev/null
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartSerializer.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.foundation.common.utils.json;
+
+import java.io.IOException;
+
+import javax.servlet.http.Part;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.ObjectCodec;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import com.fasterxml.jackson.databind.util.TokenBuffer;
+
+public class JavaxServletPartSerializer extends StdSerializer<Part> {
+ private static final long serialVersionUID = 348443113789878443L;
+
+ public JavaxServletPartSerializer() {
+ this(null);
+ }
+
+ protected JavaxServletPartSerializer(Class<Part> t) {
+ super(t);
+ }
+
+ @Override
+ public void serialize(Part value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+ final ObjectCodec preservedCodec = ((TokenBuffer) gen).asParser().getCodec();
+ // set codec as null to avoid recursive dead loop
+ // JsonGenerator is instantiated for each serialization, so there should be no thread safe issue
+ gen.setCodec(null);
+ gen.writeObject(value);
+ gen.setCodec(preservedCodec);
+ }
+}
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapperTest.java b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapperTest.java
new file mode 100644
index 0000000..81c8d35
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapperTest.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.swagger.invocation.arguments.producer;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Objects;
+
+import javax.servlet.http.Part;
+
+import org.apache.servicecomb.foundation.common.part.AbstractPart;
+import org.apache.servicecomb.swagger.invocation.SwaggerInvocation;
+import org.apache.servicecomb.swagger.invocation.arguments.ArgumentMapper;
+import org.apache.servicecomb.swagger.invocation.arguments.producer.ProducerSpringMVCQueryObjectMapperTest.RecursiveParam;
+import org.apache.servicecomb.swagger.invocation.arguments.producer.ProducerSpringMVCQueryObjectMapperTest.TestParam;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ProducerBeanParamMapperTest {
+
+ @Test
+ public void mapArgument() {
+ final HashMap<String, Integer> producerNameToSwaggerIndexMap = new HashMap<>();
+ producerNameToSwaggerIndexMap.put("name", 2);
+ producerNameToSwaggerIndexMap.put("age", 0);
+ ArgumentMapper argumentMapper = new ProducerBeanParamMapper(producerNameToSwaggerIndexMap, 0, TestParam.class);
+ SwaggerInvocation swaggerInvocation = new SwaggerInvocation();
+ swaggerInvocation.setSwaggerArguments(new Object[] {22, "abc", "nameTest"});
+
+ final Object[] producerArguments = new Object[1];
+ argumentMapper.mapArgument(swaggerInvocation, producerArguments);
+ Assert.assertEquals(producerArguments[0], new TestParam().setName("nameTest").setAge(22));
+ }
+
+ @Test
+ public void mapArgumentOnRecursiveParam() {
+ final HashMap<String, Integer> producerNameToSwaggerIndexMap = new HashMap<>();
+ producerNameToSwaggerIndexMap.put("num", 0);
+ producerNameToSwaggerIndexMap.put("str", 1);
+ producerNameToSwaggerIndexMap.put("date", 2);
+ ArgumentMapper argumentMapper = new ProducerBeanParamMapper(producerNameToSwaggerIndexMap, 1,
+ RecursiveParam.class);
+ SwaggerInvocation swaggerInvocation = new SwaggerInvocation();
+ final Date testDate = new Date();
+ swaggerInvocation.setSwaggerArguments(new Object[] {2, "str0_0", testDate});
+
+ final Object[] producerArguments = new Object[2];
+ argumentMapper.mapArgument(swaggerInvocation, producerArguments);
+ Assert.assertNull(producerArguments[0]);
+ Assert.assertEquals(producerArguments[1], new RecursiveParam().setNum(2).setStr("str0_0").setDate(testDate));
+ }
+
+ @Test
+ public void mapArgumentWithPart() {
+ final HashMap<String, Integer> producerNameToSwaggerIndexMap = new HashMap<>();
+ producerNameToSwaggerIndexMap.put("up", 0);
+ producerNameToSwaggerIndexMap.put("str", 2);
+ producerNameToSwaggerIndexMap.put("longValue", 3);
+ ArgumentMapper argumentMapper = new ProducerBeanParamMapper(producerNameToSwaggerIndexMap, 0,
+ TestParamWithPart.class);
+ SwaggerInvocation swaggerInvocation = new SwaggerInvocation();
+ final AbstractPart uploadedFile = new AbstractPart();
+ swaggerInvocation.setSwaggerArguments(new Object[] {uploadedFile, 123L, "testString", 12L});
+
+ final Object[] producerArguments = new Object[2];
+ argumentMapper.mapArgument(swaggerInvocation, producerArguments);
+ Assert.assertEquals(producerArguments[0], new TestParamWithPart("testString", 12L, uploadedFile));
+ Assert.assertSame(((TestParamWithPart) producerArguments[0]).getUp(), uploadedFile);
+ Assert.assertNull(producerArguments[1]);
+ }
+
+ static class TestParamWithPart {
+ private String str;
+
+ private long longValue;
+
+ private Part uploaded;
+
+ public TestParamWithPart() {
+ }
+
+ public TestParamWithPart(String str, long longValue, Part uploaded) {
+ this.str = str;
+ this.longValue = longValue;
+ this.uploaded = uploaded;
+ }
+
+ public String getStr() {
+ return str;
+ }
+
+ public void setStr(String str) {
+ this.str = str;
+ }
+
+ public long getLongValue() {
+ return longValue;
+ }
+
+ public void setLongValue(long longValue) {
+ this.longValue = longValue;
+ }
+
+ public Part getUp() {
+ return uploaded;
+ }
+
+ public void setUp(Part uploaded) {
+ this.uploaded = uploaded;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TestParamWithPart that = (TestParamWithPart) o;
+ return longValue == that.longValue &&
+ Objects.equals(str, that.str) &&
+ Objects.equals(uploaded, that.uploaded);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(str, longValue, uploaded);
+ }
+ }
+}