title: Unexpected character ('%' (code 37)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
body: <p>For several day I trying to figure out what this error means.
  I getting the error when i try to download file from web service.</p>
  
  <p>The full error is:</p>
  
  <pre><code>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]".
  </code></pre>
  
  <p>The class that do the job of Serialization and Deserialization from web service:</p>
  
  <pre><code>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 &lt;T&gt;      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 &lt;T&gt; T doMethod(String strUrl, HTTPMethod method, Object body,
                        Class&lt;T&gt; 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 &lt;T&gt;      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 &lt;T&gt; T doMethod(String strUrl, HTTPMethod method, Object body,
                        Class&lt;T&gt; output, Map&lt;String, String&gt; 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 &amp;&amp; method != HTTPMethod.POST) {
          String methodParam;
          if (strUrl.contains("?")) {
              methodParam = "&amp;_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&lt;String, String&gt; 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 &gt; 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();
          }
      }
   }
  }
  </code></pre>
  
  <p>The line the I used to download the file is:</p>
  
  <pre><code>try {
  FileOutputStream outputStream = new FileOutputStream(file);
  outputStream = WSClass.doMethod(Url, WSClass.HTTPMethod.GET, null, 
  FileOutputStream.class);
   } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (SocketException e) {
      e.printStackTrace();
     } catch (IOException e) {
      e.printStackTrace();
     } catch (Exception e) {
     e.printStackTrace();
    }finally {
      if (outputStream != null) {
        outputStream.flush();
         outputStream.close();
        }
     }
  </code></pre>
  
  <p>Someone knows what the problem?</p>
  
  <p><strong>UPDATE:</strong> I success to download the file.</p>
  
  <p>I change the function doMethod with @Ganesh Karewad suggested and added another way to write to fileoutputstream.</p>
  
  <pre><code>    public &lt;T&gt; T doMethod(String strUrl, HTTPMethod method, Object body,
                        Class&lt;T&gt; 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 &lt;T&gt;      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 &lt;T&gt; T doMethod(String strUrl, HTTPMethod method, Object body,
                        Class&lt;T&gt; output, Map&lt;String, String&gt; 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 &amp;&amp; method != HTTPMethod.POST) {
          String methodParam;
          if (strUrl.contains("?")) {
              methodParam = "&amp;_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&lt;String, String&gt; 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();
      }
  }
  </code></pre>
  
  <p>If i need file:
  I set to connection as "conn.setRequestProperty("Accept", "application/octet-stream");" and read the input to fileoutputstream.</p>
  
  <p>Thanks,</p>
  
  <p>Tal</p>