Java 意外字符(';%';(代码37)):应为有效值(数字、字符串、数组、对象、';true';、';false';或';null';)
我花了几天的时间试图弄明白这个错误的含义。 我尝试从web服务下载文件时遇到错误 完全错误是:Java 意外字符(';%';(代码37)):应为有效值(数字、字符串、数组、对象、';true';、';false';或';null';),java,android,web-services,Java,Android,Web Services,我花了几天的时间试图弄明白这个错误的含义。 我尝试从web服务下载文件时遇到错误 完全错误是: java.lang.RuntimeException: org.codehaus.jackson.JsonParseException: Unexpected character ('%' (code 37)): expected a valid value (number, String, array, object, 'true', 'false' or 'null') at [Source: j
java.lang.RuntimeException: org.codehaus.jackson.JsonParseException: Unexpected character ('%' (code 37)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: java.io.StringReader@39494c1; line: 1, column: 2]".
从web服务执行序列化和反序列化操作的类:
public class WSClass{
public String authenticationToken;
public enum HTTPMethod {
GET, PUT, POST, DELETE
}
// Constructor.
public WSClass() {
}
/**
* Calls a REST endpoint in the specified URL and returns
* the return value. Optionally deserializes it from JSON.
*
* @param <T> The type of the return value
* @param //strUrl URL relative to the applet root
* @param method HTTP Method used in the request
* @param body Body serialized for the JSON
* @param output The type of the return value
* @return The REST response as an instance of type T
*/
public <T> T doMethod(String strUrl, HTTPMethod method, Object body,
Class<T> output) throws IOException {
return doMethod(strUrl, method, body, output, null);
}
/**
* Calls a REST endpoint in the specified URL and returns
* the return value. Optionally deserializes it from JSON.
*
* @param <T> The type of the return value
* @param //strUrl URL relative to the applet root
* @param method HTTP Method used in the request
* @param body Body serialized for the JSON
* @param output The type of the return value
* @param headers Key-Value list of additional headers.
* @return The REST response as an instance of type T
*/
@SuppressWarnings("unchecked")
public <T> T doMethod(String strUrl, HTTPMethod method, Object body,
Class<T> output, Map<String, String> headers) throws IOException {
// Strip the first '/' away if it exists.
if (strUrl.startsWith("/")) {
strUrl = strUrl.substring(1);
}
// Calculate the real url based on method. IIS supports only the
// GET and POST in default mode so we'll use the _method parameter
// that MFWS understands.
if (method != HTTPMethod.GET && method != HTTPMethod.POST) {
String methodParam;
if (strUrl.contains("?")) {
methodParam = "&_method=";
} else {
methodParam = "?_method=";
}
strUrl += methodParam + method.name();
method = HTTPMethod.POST;
}
// Initialize JSON (de)serializer.
ObjectMapper om = new ObjectMapper();
om.configure(org.codehaus.jackson.map.SerializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS, false);
om.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS, false);
om.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// Get URL to REST interface.
URL u = new URL(strUrl);
// Perform the request.
HttpURLConnection conn = null;
OutputStream os = null;
InputStream is = null;
BufferedReader in = null;
try {
// Open connection.
conn = (HttpURLConnection) u.openConnection();
// Prevent the use of cache.
// The applet does not seem to respect the cache control flags it receives from the server.
// For example it won't necessarily make a new request to the server even if the requested
// resources has expired. See issue: #9234.
conn.setUseCaches(false);
// Set the request properties.
conn.setRequestMethod(method.name());
if (body != null)
conn.setDoOutput(true);
if (!output.equals(void.class))
conn.setDoInput(true);
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("X-Authentication", authenticationToken);
if (headers != null) {
for (Map.Entry<String, String> header : headers.entrySet()) {
System.out.println("Setting header " + header.getKey());
conn.setRequestProperty(header.getKey(), header.getValue());
}
}
// If there is a body, serialize it to the output stream.
if (body != null) {
os = conn.getOutputStream();
om.writeValue(os, body);
} else if (method != HTTPMethod.GET) {
// No body available.
conn.setRequestProperty("Content-Length", "0");
}
// Check if the caller wanted the connection as the return value.
if (output.equals(HttpURLConnection.class)) {
// Change ownership so we don't disconnect the connection in
// finalize block.
HttpURLConnection connDetached = conn;
conn = null;
return (T) connDetached;
}
// Write the output if we had output.
if (os != null) {
os.flush();
os.close();
}
os = null;
// Get response to input stream.
conn.connect();
is = conn.getInputStream();
int contentLength = conn.getContentLength();
if (output.equals(InputStream.class)) {
// If the output type is input stream, just return it
// as it is.
InputStream isReturn = is;
is = null; // Change ownership.
return (T) isReturn;
}
else {
// Deserialize from JSON object.
String response = readStringFromStream(is, contentLength);
// Read the return value from the response.
if (output.equals(void.class) || response.length() == 0)
return null;
else
return om.readValue(response, output);
} // end-if (output.equals(InputStream.class))
} catch (IOException e3) {
throw new RuntimeException(e3);
} finally {
// Close streams.
closeStream(os);
closeStream(is);
closeStream(in);
if (conn != null)
conn.disconnect();
}
}
/**
* Reads an UTF-8 encoded string from the specified stream.
*
* @param is
* @param totalLengthInBytes
* @return
* @throws IOException
*/
private String readStringFromStream(InputStream is, int totalLengthInBytes) throws IOException {
// Return empty string if the requested number of bytes is zero.
if (totalLengthInBytes == 0)
return "";
// It seems that Opera 10 may pass -1 as the total length if the actual Content-Length header
// indicates zero body length.
// Because -1 indicates unspecified content length we attempt to read as much as possible in this case.
if (totalLengthInBytes == -1)
totalLengthInBytes = Integer.MAX_VALUE;
// Read the data from the stream as bytes and pipe it through piped stream
// that converts the byte stream to UTF-8 char stream.
PipedOutputStream poutput = null;
PipedInputStream pinput = null;
StringBuilder result = new StringBuilder();
try {
// Start reading the stream.
boolean continueRead = true;
poutput = new PipedOutputStream();
pinput = new PipedInputStream(poutput);
InputStreamReader r = new InputStreamReader(pinput, "UTF-8");
int bytesReadTotal = 0;
int byteBufferSize = 500; // Buffer size used in the conversion.
CharBuffer cb = CharBuffer.allocate(byteBufferSize);
byte[] buffer = new byte[byteBufferSize];
while (continueRead) {
// Read correct number of bytes from the input stream and write the to the output buffer.
int readByteCount = Math.min(buffer.length, totalLengthInBytes - bytesReadTotal);
int bytesRead = is.read(buffer, 0, readByteCount);
// Convert the bytes to a string.
if (bytesRead > 0) {
// Write to the piped stream.
poutput.write(buffer, 0, bytesRead);
// Read the bytes as string.
cb.clear();
r.read(cb);
int charactersRead = cb.position();
// Collect the string read to the buffer.
cb.rewind();
String currentBatch = cb.subSequence(0, charactersRead).toString();
result.append(currentBatch);
} // end if
// Stop reading if EOF was encountered.
if (bytesRead == -1)
continueRead = false;
else
bytesReadTotal += bytesRead;
// Stop reading the stream after we have read all the available bytes.
if (bytesReadTotal == totalLengthInBytes)
continueRead = false;
} // end while
} finally {
// Close the middleware streams.
closeStream(poutput);
closeStream(pinput);
}
// Return the result.
return result.toString();
}
/**
* Closes the specified stream
*
* @param stream
*/
private static void closeStream(Closeable stream) {
// Try closing only if the stream was specified.
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
// Ignore error.
e.printStackTrace();
}
}
}
}
有人知道问题出在哪里
更新:我下载文件成功
我用@Ganesh Karewad建议的方法更改了函数doMethod,并添加了另一种写入fileoutputstream的方法
public <T> T doMethod(String strUrl, HTTPMethod method, Object body,
Class<T> output, File file) throws IOException {
return doMethod(strUrl, method, body, output, null, file);
}
/**
* Calls a REST endpoint in the specified URL and returns
* the return value. Optionally deserializes it from JSON.
*
* @param <T> The type of the return value
* @param //strUrl URL relative to the applet root
* @param method HTTP Method used in the request
* @param body Body serialized for the JSON
* @param output The type of the return value
* @param headers Key-Value list of additional headers.
* @return The REST response as an instance of type T
*/
@SuppressWarnings("unchecked")
public <T> T doMethod(String strUrl, HTTPMethod method, Object body,
Class<T> output, Map<String, String> headers, File file) throws IOException {
// Strip the first '/' away if it exists.
if (strUrl.startsWith("/")) {
strUrl = strUrl.substring(1);
}
// Calculate the real url based on method. IIS supports only the
// GET and POST in default mode so we'll use the _method parameter
// that MFWS understands.
if (method != HTTPMethod.GET && method != HTTPMethod.POST) {
String methodParam;
if (strUrl.contains("?")) {
methodParam = "&_method=";
} else {
methodParam = "?_method=";
}
strUrl += methodParam + method.name();
method = HTTPMethod.POST;
}
// Initialize JSON (de)serializer.
ObjectMapper om = new ObjectMapper();
om.configure(org.codehaus.jackson.map.SerializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS, false);
om.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS, false);
om.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// Get URL to REST interface.
URL u = new URL(strUrl);
// Perform the request.
HttpURLConnection conn = null;
OutputStream os = null;
InputStream is = null;
BufferedReader in = null;
try {
// Open connection.
conn = (HttpURLConnection) u.openConnection();
// Prevent the use of cache.
// The applet does not seem to respect the cache control flags it receives from the server.
// For example it won't necessarily make a new request to the server even if the requested
// resources has expired. See issue: #9234.
conn.setUseCaches(false);
// Set the request properties.
conn.setRequestMethod(method.name());
if (body != null)
conn.setDoOutput(true);
if (!output.equals(void.class))
conn.setDoInput(true);
if(file != null)
{
conn.setRequestProperty("Accept", "application/octet-stream");
}
else
{
conn.setRequestProperty("Accept", "application/json");
}
conn.setRequestProperty("X-Authentication", authenticationToken);
if (headers != null) {
for (Map.Entry<String, String> header : headers.entrySet()) {
System.out.println("Setting header " + header.getKey());
conn.setRequestProperty(header.getKey(), header.getValue());
}
}
// If there is a body, serialize it to the output stream.
if (body != null) {
os = conn.getOutputStream();
om.writeValue(os, body);
} else if (method != HTTPMethod.GET) {
// No body available.
conn.setRequestProperty("Content-Length", "0");
}
// Check if the caller wanted the connection as the return value.
if (output.equals(HttpURLConnection.class)) {
// Change ownership so we don't disconnect the connection in
// finalize block.
HttpURLConnection connDetached = conn;
conn = null;
return (T) connDetached;
}
// Write the output if we had output.
if (os != null) {
os.flush();
os.close();
}
os = null;
// Get response to input stream.
conn.connect();
is = conn.getInputStream();
String response = null;
int contentLength = conn.getContentLength();
if (output.equals(InputStream.class)) {
// If the output type is input stream, just return it
// as it is.
InputStream isReturn = is;
is = null; // Change ownership.
return (T) isReturn;
}
else {
if(file != null)
{
FileOutputStream fileOut = new FileOutputStream(file);
IOUtils.copy(is, fileOut);
return om.readValue("true", output);
}
else
{
// Deserialize from JSON object.
response = readStringFromStream(is, contentLength);
}
// Read the return value from the response.
if (output.equals(void.class) || response.length() == 0)
return null;
else
return om.readValue(response, output);
} // end-if (output.equals(InputStream.class))
} catch (IOException e3) {
throw new RuntimeException(e3);
} finally {
// Close streams.
closeStream(os);
closeStream(is);
closeStream(in);
if (conn != null)
conn.disconnect();
}
}
public T doMethod(字符串结构、HTTPMethod方法、对象体、,
类输出,文件)引发IOException{
返回doMethod(strUrl,method,body,output,null,file);
}
/**
*调用指定URL中的REST端点并返回
*返回值。可选地从JSON反序列化它。
*
*@param返回值的类型
*@param//strUrl相对于小程序根的URL
*@param method请求中使用的HTTP方法
*@param body已为JSON序列化
*@param输出返回值的类型
*@param headers附加头的键值列表。
*@将REST响应作为类型T的实例返回
*/
@抑制警告(“未选中”)
公共T方法(字符串结构、HTTPMethod方法、对象体、,
类输出、映射头、文件)引发IOException{
//如果第一个“/”存在,请将其去掉。
if(strUrl.startsWith(“/”){
strUrl=strUrl.子串(1);
}
//基于方法计算实际url。IIS仅支持
//在默认模式下获取和发布,因此我们将使用_方法参数
//MFWS理解这一点。
if(method!=HTTPMethod.GET&&method!=HTTPMethod.POST){
字符串方法参数;
if(结构包含(“?”){
methodParam=“&_method=”;
}否则{
methodParam=“?_method=”;
}
strUrl+=methodParam+method.name();
方法=HTTPMethod.POST;
}
//初始化JSON(反)序列化程序。
ObjectMapper om=新的ObjectMapper();
configure(org.codehaus.jackson.map.SerializationConfig.Feature.CAN\u OVERRIDE\u ACCESS\u MODIFIERS,false);
configure(org.codehaus.jackson.map.DeserializationConfig.Feature.CAN\u OVERRIDE\u ACCESS\u MODIFIERS,false);
configure(org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL\u ON\u UNKNOWN\u属性,false);
//获取REST接口的URL。
URL u=新的URL(strUrl);
//执行请求。
HttpURLConnection conn=null;
OutputStream os=null;
InputStream=null;
BufferedReader in=null;
试一试{
//打开连接。
conn=(HttpURLConnection)u.openConnection();
//防止使用缓存。
//小程序似乎不遵守从服务器接收的缓存控制标志。
//例如,它不一定会向服务器发出新请求,即使请求
//资源已过期。请参阅问题:#9234。
conn.SETUSECHACHES(假);
//设置请求属性。
conn.setRequestMethod(method.name());
if(body!=null)
连接设置输出(真);
如果(!output.equals(void.class))
conn.setDoInput(真);
如果(文件!=null)
{
conn.setRequestProperty(“接受”、“应用程序/八位字节流”);
}
其他的
{
conn.setRequestProperty(“接受”、“应用程序/json”);
}
conn.setRequestProperty(“X-Authentication”,authenticationToken);
如果(标题!=null){
for(Map.Entry头:headers.entrySet()){
System.out.println(“设置头”+头.getKey());
conn.setRequestProperty(header.getKey(),header.getValue());
}
}
//如果有正文,则将其序列化到输出流。
if(body!=null){
os=conn.getOutputStream();
om.writeValue(操作系统,主体);
}else if(method!=HTTPMethod.GET){
//没有人。
conn.setRequestProperty(“内容长度”,“0”);
}
//检查调用方是否希望连接作为返回值。
if(output.equals(HttpURLConnection.class)){
//更改所有权,这样我们就不会断开中的连接
//最后定稿。
HttpURLConnection=conn;
conn=null;
返回(T)值;
}
//如果我们有输出,就写输出。
如果(os!=null){
os.flush();
os.close();
}
os=null;
//获取对输入流的响应。
连接();
is=conn.getInputStream();
字符串响应=null;
int contentLength=conn.getContentLength();
if(output.equals(InputStream.class)){
//如果输出类型是输入流,只需返回它
//事实就是这样。
InputStream isReturn=is;
is=null;//更改所有权。
返回(T)isReturn;
}
否则{
如果(文件!=null)
{
FileOutputStream fileOut=新的FileOutputStream(文件);
IOUtils.copy(is,fileOut);
返回om.readValue(“真”,输出);
}
其他的
{
//从JSON对象反序列化。
response=readStringFromStream(是,contentLength);
}
//从响应中读取返回值。
if(output.equals(void.class)| response.length()==0)
返回null;
其他的
返回om.readValue(响应、输出);
}//如果(output.equals(InputStream.class))结束
}捕获(IOE3异常){
抛出新的运行时异常
public <T> T doMethod(String strUrl, HTTPMethod method, Object body,
Class<T> output, File file) throws IOException {
return doMethod(strUrl, method, body, output, null, file);
}
/**
* Calls a REST endpoint in the specified URL and returns
* the return value. Optionally deserializes it from JSON.
*
* @param <T> The type of the return value
* @param //strUrl URL relative to the applet root
* @param method HTTP Method used in the request
* @param body Body serialized for the JSON
* @param output The type of the return value
* @param headers Key-Value list of additional headers.
* @return The REST response as an instance of type T
*/
@SuppressWarnings("unchecked")
public <T> T doMethod(String strUrl, HTTPMethod method, Object body,
Class<T> output, Map<String, String> headers, File file) throws IOException {
// Strip the first '/' away if it exists.
if (strUrl.startsWith("/")) {
strUrl = strUrl.substring(1);
}
// Calculate the real url based on method. IIS supports only the
// GET and POST in default mode so we'll use the _method parameter
// that MFWS understands.
if (method != HTTPMethod.GET && method != HTTPMethod.POST) {
String methodParam;
if (strUrl.contains("?")) {
methodParam = "&_method=";
} else {
methodParam = "?_method=";
}
strUrl += methodParam + method.name();
method = HTTPMethod.POST;
}
// Initialize JSON (de)serializer.
ObjectMapper om = new ObjectMapper();
om.configure(org.codehaus.jackson.map.SerializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS, false);
om.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS, false);
om.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// Get URL to REST interface.
URL u = new URL(strUrl);
// Perform the request.
HttpURLConnection conn = null;
OutputStream os = null;
InputStream is = null;
BufferedReader in = null;
try {
// Open connection.
conn = (HttpURLConnection) u.openConnection();
// Prevent the use of cache.
// The applet does not seem to respect the cache control flags it receives from the server.
// For example it won't necessarily make a new request to the server even if the requested
// resources has expired. See issue: #9234.
conn.setUseCaches(false);
// Set the request properties.
conn.setRequestMethod(method.name());
if (body != null)
conn.setDoOutput(true);
if (!output.equals(void.class))
conn.setDoInput(true);
if(file != null)
{
conn.setRequestProperty("Accept", "application/octet-stream");
}
else
{
conn.setRequestProperty("Accept", "application/json");
}
conn.setRequestProperty("X-Authentication", authenticationToken);
if (headers != null) {
for (Map.Entry<String, String> header : headers.entrySet()) {
System.out.println("Setting header " + header.getKey());
conn.setRequestProperty(header.getKey(), header.getValue());
}
}
// If there is a body, serialize it to the output stream.
if (body != null) {
os = conn.getOutputStream();
om.writeValue(os, body);
} else if (method != HTTPMethod.GET) {
// No body available.
conn.setRequestProperty("Content-Length", "0");
}
// Check if the caller wanted the connection as the return value.
if (output.equals(HttpURLConnection.class)) {
// Change ownership so we don't disconnect the connection in
// finalize block.
HttpURLConnection connDetached = conn;
conn = null;
return (T) connDetached;
}
// Write the output if we had output.
if (os != null) {
os.flush();
os.close();
}
os = null;
// Get response to input stream.
conn.connect();
is = conn.getInputStream();
String response = null;
int contentLength = conn.getContentLength();
if (output.equals(InputStream.class)) {
// If the output type is input stream, just return it
// as it is.
InputStream isReturn = is;
is = null; // Change ownership.
return (T) isReturn;
}
else {
if(file != null)
{
FileOutputStream fileOut = new FileOutputStream(file);
IOUtils.copy(is, fileOut);
return om.readValue("true", output);
}
else
{
// Deserialize from JSON object.
response = readStringFromStream(is, contentLength);
}
// Read the return value from the response.
if (output.equals(void.class) || response.length() == 0)
return null;
else
return om.readValue(response, output);
} // end-if (output.equals(InputStream.class))
} catch (IOException e3) {
throw new RuntimeException(e3);
} finally {
// Close streams.
closeStream(os);
closeStream(is);
closeStream(in);
if (conn != null)
conn.disconnect();
}
}
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Accept", "application/octet-stream");
conn.setRequestProperty("Accept", "image/png");