解析Android应用程序发送的JSON数据

时间:2014-02-01 06:16:02

标签: java android json nullpointerexception servlet-3.0

hmkcode.com发布的应用程序从用户那里获取了一些数据,解析& 转换发送到名为jsonservlet的java servlet。我更改了解析的输入值,但每次NullPointerException我都会收到。

java.lang.NullPointerException
    java.io.StringReader.<init>(StringReader.java:50)
    com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:796)
    com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
    iaau.uimsmobile.getData.getDataServlet.doPost(getDataServlet.java:48)
    iaau.uimsmobile.getData.getDataServlet.doGet(getDataServlet.java:65)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)

LogCat跟踪

02-01 10:31:38.232      424-424/com.iaaum D/dalvikvm﹕ GC_EXTERNAL_ALLOC freed 81K, 52% free 2630K/5379K, external 904K/1038K, paused 72ms
02-01 10:32:03.392      424-424/com.iaaum W/KeyCharacterMap﹕ No keyboard for id 0
02-01 10:32:03.392      424-424/com.iaaum W/KeyCharacterMap﹕ Using default keymap: /system/usr/keychars/qwerty.kcm.bin
02-01 10:32:08.962      424-433/com.iaaum D/InputStream﹕ Connection to http://localhost:8080 refused
02-01 10:34:28.142      424-434/com.iaaum D/InputStream﹕ Connection to http://localhost:8080 refused

最后,我在两侧的toString()方法中更改了JSON格式的字符串。 @SotiriosDelimanolis谈到的失败是

com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
 at [Source: java.io.StringReader@30b3b5; line: 1, column: 1]
    com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
    com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:2931)
    com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2873)
    com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
    iaau.uimsmobile.getData.getDataServlet.doPost(getDataServlet.java:48)
    iaau.uimsmobile.getData.getDataServlet.doGet(getDataServlet.java:65)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)

  

客户端 - &gt;的 User.java

public class User{
private String IDnumber;
private String Password;

public String getIDnumber() {
    return IDnumber;
}

public void setIDnumber(String IDnumber) {
    this.IDnumber = IDnumber;
}

public String getPassword() {
    return Password;
}

public void setPassword(String password) {
    Password = password;
}

@Override
public String toString()
{
 // { "IDnumber":"" , "Password":"" }
    return "{\"IDnumber\":"+"\""+IDnumber+"\""+",\"Password\":"+"\""+Password+"\"}";
}
}

  

客户端 - &gt;的 LoginActivity.java

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import android.widget.Toast;

import com.iaaum.user.User;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class LoginActivity extends Activity implements OnClickListener
{
    TextView IsConnected;
    EditText id_number;
    EditText password;
    Button sign_button;

    User current_user;

    public String urlAddress = "http://192.168.1.101:8080/UIMSMobile/getDataServlet";
  //public String urlAddress = "http://127.0.0.1:8080/UIMSMobile/getDataServlet"; 
  //public String urlAddress = "http://localhost:8080/UIMSMobile/getDataServlet";

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_login);

        // get reference to the views
        IsConnected = (TextView) findViewById(R.id.isConnected);

        id_number = (EditText) findViewById(R.id.id_number);
        password = (EditText) findViewById(R.id.password);

        sign_button= (Button) findViewById(R.id.sign_in_button);

        // check if you are connected or not
        if(IsConnectedMethod())
        {
            IsConnected.setBackgroundColor(0xFF00CC00);
            IsConnected.setText("You are connected");
        }
        else{
            IsConnected.setText("You are NOT connected");
        }

        // add click listener to Button "POST"
        sign_button.setOnClickListener(this);
    }

    @Override
    public void onClick(View view)
    {

        switch(view.getId()){
            case R.id.sign_in_button:
                if(!validate())
                    Toast.makeText(getBaseContext(), "Enter some data!", Toast.LENGTH_LONG).show();
                // call AsyncTask to perform network operation on separate thread
                new HttpAsyncTask().execute(urlAddress);
                break;
        }

    }

    public boolean IsConnectedMethod()
    {
        ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Activity.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        return networkInfo != null && networkInfo.isConnected();
   }

    public static String Post(String url, User current_user)
    {
        InputStream inputStream = null;
        String result = "";

        try
        {
            // 1. create HttpClient
            HttpClient httpclient = new DefaultHttpClient();

            // 2. make POST request to the given URL
            HttpPost httpPost = new HttpPost(url);

            String json = "";


            // 3. build jsonObject
            JSONObject jsonObject = new JSONObject();

            jsonObject.accumulate("IDnumber", current_user.getIDnumber());
            jsonObject.accumulate("Password", current_user.getPassword());

            // 4. convert JSONObject to JSON in String
            json = jsonObject.toString();

            // ** Alternative way to convert Person object to JSON string using Jackson Lib
            // ObjectMapper mapper = new ObjectMapper();
            // json = mapper.writeValueAsString(person);

            // 5. set json to StringEntity
            StringEntity se = new StringEntity(json);

            // 6. set httpPost Entity
            httpPost.setEntity(se);

            // 7. Set some headers to inform server about the type of the content
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");

            // 8. Execute POST request to the given URL
            HttpResponse httpResponse = httpclient.execute(httpPost);

            // 9. receive response as inputStream
            inputStream = httpResponse.getEntity().getContent();


            // 10. convert inputstream to string
            if(inputStream != null)
                result = convertInputStreamToString(inputStream);
            else
                result = "Did not work!";

        } catch (Exception e) {
            Log.d("InputStream", e.getLocalizedMessage());
        }

        // 11. return result
        return result;
    }


    private class HttpAsyncTask extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... urls)
        {
            current_user = new User();
            current_user.setIDnumber(id_number.getText().toString());
            current_user.setPassword(password.getText().toString());

            return Post(urls[0], current_user);
        }
        // onPostExecute displays the results of the AsyncTask.
        @Override
        protected void onPostExecute(String result) {
            Toast.makeText(getBaseContext(), "Data Sent!", Toast.LENGTH_LONG).show();
        }
    }


    private boolean validate()
    {
        if(id_number.getText().toString().trim().equals(""))
            return false;
        else return !password.getText().toString().trim().equals("");
    }

    private static String convertInputStreamToString(InputStream inputStream) throws IOException {
        BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
        String line = "";
        String result = "";
        while((line = bufferedReader.readLine()) != null)
            result += line;

        inputStream.close();
        return result;
    }

}
  

客户端 - &gt;的的AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.iaaum" >

    <uses-sdk
        android:minSdkVersion="8"
        android:maxSdkVersion="19"
        />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET"/>


    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity
            android:name="com.iaaum.LoginActivity"
            android:label="@string/title_activity_login" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
  

服务器端 - &gt;的 User.java

public class User 
{
    private String idnumber;
    private String password;

    public User(String idnumber, String password) {
        this.idnumber = idnumber;
        this.password = password;
    }

    public String getIDnumber() {
        return idnumber;
    }

    public void setIDnumber(String idnumber) {
        this.idnumber = idnumber;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString()
    {
        return "{\"IDnumber\":"+"\""+idnumber+"\""+",\"Password\":"+"\""+password+"\"}";
    }        
}
  

服务器端 - &gt;的 getDataServlet.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.fasterxml.jackson.databind.ObjectMapper;


public class getDataServlet extends HttpServlet 
{

    private static final long serialVersionUID = 1L;

    // This will store all received articles
    List<User> _users = new LinkedList<User>();

    /***************************************************
     * URL: /getDataServlet
     * doPost(): receives JSON data, parse it, map it and send back as JSON
     * @param request
     * @param response
     * @throws javax.servlet.ServletException
     * @throws java.io.IOException
     ****************************************************/
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
        {

        // 1. get received JSON data from request
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String json = "";

            if(br.readLine() != null)
            {
                 json = br.readLine();
            }

        // 2. initiate jackson mapper
                ObjectMapper mapper = new ObjectMapper();

                // 3. Convert received JSON to User
                User _user = mapper.readValue(json, User.class);

        // 4. Set response type to JSON
        response.setContentType("application/json");            

                // 5. Add article to List<Article>
        _users.add(_user);

        // 6. Send List<Article> as JSON to client
                mapper.writeValue(response.getOutputStream(), _users);
    }



    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    {
        doPost(request, response);

    }
    @Override
    public String getServletInfo() 
    {
        return "Short description";
    }

}

3 个答案:

答案 0 :(得分:1)

可以抛出异常的唯一方法是,如果您传入的String json

mapper.readValue(json, User.class);

null

你这里做错了什么

if(br != null)
{
    json = br.readLine();
}

br永远不会null。也许你的意思是

String temp;
if ((temp = br.readLine()) != null)
{
    json = temp;
}

甚至更好,将流直接传递给ObjectMapper的一个重载readValue(..)方法并处理任何错误。

在任何情况下,您似乎都没有在请求正文中发送任何内容,因此readLine()会返回您分配给null的{​​{1}}并导致失败json

您的ObjectMapper正在委派给您doGet()。你有可能发送GET请求吗?

答案 1 :(得分:0)

通过处理您的建议,我对代码进行了一些更改,现在应用程序正在运行。以下是更改:

服务器端---&gt; getDataServlet.java


package com.****;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.****.dao.User;

public class getDataServlet extends HttpServlet 
{
    private static final long serialVersionUID = 1L;
    List<User> users = new LinkedList<User>();

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {

        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String json = "";
        if(br != null){
            json = br.readLine();}
        ObjectMapper mapper = new ObjectMapper();
        User user = mapper.readValue(json, User.class);
        response.setContentType("application/json");            
        if(users.size() > 20){
            users.remove(0);}
        users.add(user);
        mapper.writeValue(response.getOutputStream(), users);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
    {

        ObjectMapper mapper = new ObjectMapper();
        resp.setContentType("application/json");            
        mapper.writeValue(resp.getOutputStream(), users);
    }
}

服务器端 - &gt; User.java


package com.*****.dao;

public class User {

    private String idnumber;
    private String password;

    public String getIdnumber() {
        return idnumber;
    }

    public void setIdnumber(String idnumber) {
        this.idnumber = idnumber;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User [idnumber=" + idnumber + ", password=" + password  + "]";
    }
}

客户端---&gt; MainActivity.java

JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("idnumber", user.getIdnumber());
jsonObject.accumulate("password", user.getPassword());

客户端---&gt; User.java

@Override
public String toString() 
{
    return "User [idnumber=" + idnumber + ", password=" + password + "]";
}

发布后数据输出后:

  

[{“idnumber”:“987654321”,“密码”:“123456789”}]

答案 2 :(得分:-1)

解决方案1:

如果您使用localhost,那么可能是您提供网址的问题,然后使用IP Address代替localhost

您可以使用ipconfig命令在命令提示符中检查IP。

解决方案2:

User.java 中,您可能必须使用JSONObjectJSONArraytoString()方法中创建JSON字符串。