diff --git a/org.springframework.web/ivy.xml b/org.springframework.web/ivy.xml index b2bf5513f1..095e765494 100644 --- a/org.springframework.web/ivy.xml +++ b/org.springframework.web/ivy.xml @@ -1,9 +1,9 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd" + version="1.3"> @@ -17,6 +17,7 @@ + @@ -30,48 +31,50 @@ + conf="optional, hessian, burlap->compile"/> + conf="provided, faces->compile"/> + conf="provided, jsp->compile"/> + conf="provided, jaxrpc->compile"/> + conf="provided, ws->compile"/> + conf="optional, axis->compile"/> + conf="optional, httpclient->compile"/> + conf="compile->compile"/> + conf="optional, log4j->compile"/> + + conf="compile->compile"/> + conf="compile->compile"/> + conf="compile->compile"/> + conf="compile->compile"/> - - + conf="optional, compile->compile"/> + + + conf="test->compile"/> + conf="test->compile"/> diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/json/JacksonHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/json/JacksonHttpMessageConverter.java new file mode 100644 index 0000000000..fcabf37d6b --- /dev/null +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/json/JacksonHttpMessageConverter.java @@ -0,0 +1,88 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed 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.springframework.http.converter.json; + +import java.io.IOException; +import java.nio.charset.Charset; + +import org.codehaus.jackson.JsonEncoding; +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.MappingJsonFactory; +import org.codehaus.jackson.map.ObjectMapper; + +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.MediaType; +import org.springframework.http.converter.AbstractHttpMessageConverter; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.util.Assert; + +/** + * @author Arjen Poutsma + * @since 3.0 + */ +public class JacksonHttpMessageConverter extends AbstractHttpMessageConverter { + + private ObjectMapper objectMapper = new ObjectMapper(); + + private JsonFactory jsonFactory = new MappingJsonFactory(); + + private JsonEncoding encoding = JsonEncoding.UTF8; + + public JacksonHttpMessageConverter() { + super(new MediaType("application", "json")); + } + + public void setObjectMapper(ObjectMapper objectMapper) { + Assert.notNull(objectMapper, "'objectMapper' must not be null"); + this.objectMapper = objectMapper; + } + + public void setJsonFactory(JsonFactory jsonFactory) { + Assert.notNull(jsonFactory, "'jsonFactory' must not be null"); + this.jsonFactory = jsonFactory; + } + + public void setEncoding(JsonEncoding encoding) { + this.encoding = encoding; + } + + public boolean supports(Class clazz) { + return objectMapper.canSerialize(clazz); + } + + @Override + protected T readInternal(Class clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + return objectMapper.readValue(inputMessage.getBody(), clazz); + } + + @Override + protected MediaType getContentType(T t) { + Charset charset = Charset.forName(encoding.getJavaName()); + return new MediaType("application", "json", charset); + } + + @Override + protected void writeInternal(T t, HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(outputMessage.getBody(), encoding); + objectMapper.writeValue(jsonGenerator, t); + } +} diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/json/package-info.java b/org.springframework.web/src/main/java/org/springframework/http/converter/json/package-info.java new file mode 100644 index 0000000000..6133ac51f1 --- /dev/null +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/json/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed 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. + */ + +/** + * + * Provides a HttpMessageConverter implementations for handling JSON. + * + */ +package org.springframework.http.converter.json; + diff --git a/org.springframework.web/src/test/java/org/springframework/http/converter/json/JacksonHttpMessageConverterTest.java b/org.springframework.web/src/test/java/org/springframework/http/converter/json/JacksonHttpMessageConverterTest.java new file mode 100644 index 0000000000..0c93e1ff88 --- /dev/null +++ b/org.springframework.web/src/test/java/org/springframework/http/converter/json/JacksonHttpMessageConverterTest.java @@ -0,0 +1,141 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed 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.springframework.http.converter.json; + +import java.io.IOException; +import java.nio.charset.Charset; + +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.http.MediaType; +import org.springframework.http.MockHttpInputMessage; +import org.springframework.http.MockHttpOutputMessage; + +/** @author Arjen Poutsma */ +public class JacksonHttpMessageConverterTest { + + private JacksonHttpMessageConverter converter; + + @Before + public void setUp() { + converter = new JacksonHttpMessageConverter(); + } + + @Test + public void read() throws IOException { + String body = + "{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}"; + MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8")); + inputMessage.getHeaders().setContentType(new MediaType("application", "json")); + MyBean result = converter.read(MyBean.class, inputMessage); + assertEquals("Foo", result.getString()); + assertEquals(42, result.getNumber()); + assertEquals(42F, result.getFraction(), 0F); + assertArrayEquals(new String[]{"Foo", "Bar"}, result.getArray()); + assertTrue(result.isBool()); + assertArrayEquals(new byte[]{0x1, 0x2}, result.getBytes()); + } + + @Test + public void write() throws IOException { + MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); + MyBean body = new MyBean(); + body.setString("Foo"); + body.setNumber(42); + body.setFraction(42F); + body.setArray(new String[]{"Foo", "Bar"}); + body.setBool(true); + body.setBytes(new byte[]{0x1, 0x2}); + converter.write(body, outputMessage); + Charset utf8 = Charset.forName("UTF-8"); + String result = outputMessage.getBodyAsString(utf8); + assertTrue(result.contains("\"string\":\"Foo\"")); + assertTrue(result.contains("\"number\":42")); + assertTrue(result.contains("fraction\":42.0")); + assertTrue(result.contains("\"array\":[\"Foo\",\"Bar\"]")); + assertTrue(result.contains("\"bool\":true")); + assertTrue(result.contains("\"bytes\":\"AQI=\"")); + assertEquals("Invalid content-type", new MediaType("application", "json", utf8), + outputMessage.getHeaders().getContentType()); + } + + public static class MyBean { + + private String string; + + private int number; + + private float fraction; + + private String[] array; + + private boolean bool; + + private byte[] bytes; + + public byte[] getBytes() { + return bytes; + } + + public void setBytes(byte[] bytes) { + this.bytes = bytes; + } + + public boolean isBool() { + return bool; + } + + public void setBool(boolean bool) { + this.bool = bool; + } + + public String getString() { + return string; + } + + public void setString(String string) { + this.string = string; + } + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + public float getFraction() { + return fraction; + } + + public void setFraction(float fraction) { + this.fraction = fraction; + } + + public String[] getArray() { + return array; + } + + public void setArray(String[] array) { + this.array = array; + } + } + +} diff --git a/org.springframework.web/template.mf b/org.springframework.web/template.mf index cd0c166808..1c137a70ca 100644 --- a/org.springframework.web/template.mf +++ b/org.springframework.web/template.mf @@ -4,6 +4,7 @@ Bundle-Vendor: SpringSource Bundle-ManifestVersion: 2 Import-Template: com.caucho.*;version="[3.1.5, 4.0.0)";resolution:=optional, + org.codehaus.jackson.*;version="[1.0.0, 1.1.0)";resolution:=optional, com.sun.net.*;version="0";resolution:=optional, javax.el.*;version="[1.0.0, 2.0.0)";resolution:=optional, javax.faces.*;version="[1.1.0, 3.0.0)";resolution:=optional, diff --git a/org.springframework.web/web.iml b/org.springframework.web/web.iml index 0642a5f54a..63f894ad67 100644 --- a/org.springframework.web/web.iml +++ b/org.springframework.web/web.iml @@ -245,6 +245,28 @@ + + + + + + + + + + + + + + + + + + + + + +