iT邦幫忙

0

Json 當資料=null 的問題

有個問題想要請教:

因是使用Json 讀取,如果name 沒有資料,想要用Toast顯示無資料, 相反的,如果name 有資料,在recyclerview會顯示資料。
但我的問題點在於,如果name 沒有任何資料,程式碼則完全沒有反應,我用name.length==null 或是 name.length==0 或是 name.length< 1 或是 name.isEmpty() 都一樣,想要知道這是為什麼??? 能不能請給我一個方向? 因我已想不出到底是為什麼?

   if(Region.equals(name) & dt1.getTime() < dt2.getTime()){
                        Log.i("Volley12", String.valueOf(name.length()));
                        citymovie citymovie = new      city(name,Add,Start,End,Location,Picture1,px,py);
                        movieList.add(citymovie);
                        mAdapter.notifyDataSetChanged();

                        if(name.length() <1){
                            Toast.makeText(getApplication(), "小於1",
                                    Toast.LENGTH_LONG).show();


                        }

謝謝

看更多先前的討論...收起先前的討論...
ch_lute iT邦新手 5 級 ‧ 2020-08-03 11:11:25 檢舉
name == null看看
有試過下中斷去查看name.length()內的狀態是什麼嗎@@?
ch_lute iT邦新手 5 級 ‧ 2020-08-03 11:17:18 檢舉
如果name是null的話,name.length()應該會錯誤吧,不太確定,因為我也不知道原PO是什麼語言
我有log 過,當name 沒有值時,程式碼完全沒有反應。原本是想要藉由length =0 來當一個判斷,但不明白的是在於當name 有抓到值時,程式碼正常執行,但name 沒有值時,程式碼則沒有反應。

抱歉!! 我忘了寫我是用android studio 的Java~
剛有試著用name == null,程式碼也一樣沒有反應~
該不會是因為你的第一個If少了一個 } 吧
雖然我不知道是不是擷取錯誤...畢竟有點小跑版
我有確認過,符號確認沒有少~~ 因程式碼我想說直接貼問題的精華點出來!!!!!
fillano iT邦超人 1 級 ‧ 2020-08-03 13:23:41 檢舉
if(!!name) {有} else {無}
fillano iT邦超人 1 級 ‧ 2020-08-03 13:27:43 檢舉
你沒貼name怎樣來的,如果他是物件的一個key值,也可以用Object.keys(物件)然後看結果的陣列中有沒有這個key值,例如if(arr.indexOf(name) > -1) {有} else {無}。
fillano iT邦超人 1 級 ‧ 2020-08-03 14:03:53 檢舉
阿?我錯了...你在Java,算我沒說XD
@fillano if(!!name) {有} else {無}

我之前在網路上看時,也有看到 一篇類似的,但一直不明白name 的前面為什麼要放驚嘆號?!!!!!
那個是JS用來檢查該變數是否存在
原來如此~

1 個回答

2
浩瀚星空
iT邦超人 1 級 ‧ 2020-08-03 11:33:23
最佳解答

null是一種很奇特的東西。它不是值、不是東西、什麼都沒有。
在任何應用程式上,當碰到null要很特別的小心使用。

有些程式語言,是還可以用==null來做判斷。
但有些則是不行。

有的根本沒有所謂null值。如java或javascript。

當碰到所謂不存在的值判斷。要很特別的小心。
由於不太清楚你是用什麼語言寫的。但看起來很像是java之類的。

看更多先前的回應...收起先前的回應...
通靈亡 iT邦研究生 5 級 ‧ 2020-08-03 11:42:11 檢舉

有的根本沒有所謂null值。如java或javascript

路過問一下,星空大大為啥會說「javascript」沒有所謂的null值

由於不太清楚你是用什麼語言寫的。但看起來很像是java之類的。

Code有Log.i和Toast,應該是用Java寫Android

Yes! 是java~ 但為什麼 isEmpty()也一樣???? 真的是不懂想要求解!! 跪求拜託!!!!!

我明白你想這樣問的意思。因為實際上還是可以用 = null這樣的語法。
這個問題其實就得從名詞的解釋來看起。
實際性的null及假像性的null。

其實如果我說 undefined 因該就可以明白。
但要了解到一件事,認真來說,undefined 雖等同是 null 。但它又不是 null 。很奇妙吧。

上面我說了,這需要從名詞上來解釋了。
如將null等成一個值。那javascript就是有null。畢竟可以給值。
如將null當一種表現。那javascript就不會有null。
null是一個很奇妙的東西。你要說它是不是值?感覺像值但又不是值。
去思考這個問題看看吧。
但個人有個人的解釋。這個問題早在10多年前就曾經有過很大的爭議。
php的許多函數,也因為null這個東西變動過許多解釋及應用。

現在大約是固定了。同一解釋。
可能只有比較老的人才會比較過null吧。

通靈亡 iT邦研究生 5 級 ‧ 2020-08-03 11:56:31 檢舉

我覺得樓主在取得JSON的時候
可以用Has去判斷有沒有「name」這個Key存在
如果name 不存在,給name一個值
避免null跟undefined或甚至像星空大大說得連null都沒有

如果可以的話附上JSON的範例Sample
這樣會更清楚問題在哪邊

這個給你參考,你研究看看:
https://stackoverflow.com/questions/17487205/how-to-check-if-a-json-key-exists

Shihjoanna
我剛上面說了php有部份的函數,也為了null改變很多次解釋。
如isEmpty。在許多年前,並未將null視為是空值。
因為它不是值,一種不存在的觀念。不該將其視為空值。
畢竟也無法比較。在程式中不存在就是不存在。這也就跟不能除於0這樣的觀念有點類同。

一直到最後,其實到現在還是有部份的應用。還是認為null本來就不能當比較。其中一例就是sql了。

在php則是已經將null當成isEmpty。(但可以調整ini視為不存在)
在 java裏,很好玩的是將null列成一種特別的值。
它不屬於任何型別,但它可以存在任何型別上。

宣告時不會有事,但使用它則常會發生空指標異常的問題。
所以使用它要很小心。

謝謝通靈亡! 但我想還是要先說一下:我是真的已不知道問題在哪,才把程式碼貼出來~ 希望不要引起不必要誤會~~

我的流程如下:

  1. 我的Json 資料從觀光局那邊去抓的,網址:https://gis.taiwan.net.tw/XMLReleaseALL_public/activity_C_f.json
  2. 資料我已確認有載入,因在一開始先將資料載入時,之前有先用了log去確認過
  3. 載入後,先過濾,例如使用者之前是按了台北市,則留下台北市的資料,其它的皆已濾掉~
  4. 濾掉之後,再比對日期,如果是已過期的資料,也不保留。 只保留有效的日期
  5. 我問前遇到的問題在於:基隆市目前沒有資料,但就會回到我一開始問的問題,沒有活動,我想要至少能顯示“無資料“,但程式碼一直跑不了~~

下方附上我的程式碼:

public class Main2Activity extends AppCompatActivity {
    RecyclerView recyclerView;
    private List<citymovie> movieList = new ArrayList<>();
    private citymovieadapter mAdapter;
    String name;

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

        Intent intent = this.getIntent();
        name = intent.getStringExtra("name");
       // Toast.makeText(this, name, Toast.LENGTH_SHORT).show();

        recyclerView = (RecyclerView) findViewById(R.id.cityactivity);
        mAdapter = new citymovieadapter(movieList);
        recyclerView.setHasFixedSize(true);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
       // layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(mAdapter);

        new TransTask1().execute("https://gis.taiwan.net.tw/XMLReleaseALL_public/activity_C_f.json");
    }

    class TransTask1 extends AsyncTask<String, Void, String> {

        StringBuffer json = new StringBuffer();

        @Override
        protected String doInBackground(String... params) {

            try {
                URL url = new URL(params[0]);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                InputStream is = connection.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String line = br.readLine();
                while (line != null) {
                    json.append(line);
                    line = br.readLine();
                }

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return json.toString();
        }


        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            JSONObject jonObject = null;

            try {
                jonObject = new JSONObject(s.toString());
                JSONArray contacts = jonObject.getJSONObject("XML_Head").getJSONObject("Infos").getJSONArray("Info");
                for (int i = 0; i < contacts.length(); i++) {
                    JSONObject c = contacts.getJSONObject(i);
                    String sna = c.getString("Name");
                    String Region = c.getString("Region");
                    String Add = c.getString("Add");
                    String Start1 = c.getString("Start");
                    String Location = c.getString("Location");
                    String px = c.getString("Px");
                    String py = c.getString("Py");
                    String Description = c.getString("Description");

                    String Start = Start1.substring(0,10);
                    String Picture1 = c.getString("Picture1");
                    String Picture2 = c.getString("Picture2");
                    String Picture3 = c.getString("Picture3");
                    String End1 = c.getString("End");
                    String End = End1.substring(0,10);

                  //  Log.i("Volley", sna);

                    Calendar mCal = Calendar.getInstance();
                    String dateformat = "yyyy-MM-dd";
                    SimpleDateFormat df = new SimpleDateFormat(dateformat);
                    String today = df.format(mCal.getTime());

                    Date dt1 = df.parse(today);
                    Date dt2 = df.parse(End);


                    if(Region.equals(name) & dt1.getTime() < dt2.getTime()){
                        Log.i("Volley12", String.valueOf(sna.length()));
                        citymovie citymovie = new citymovie(sna,Add,Start,End,Location,Picture1,px,py,Picture2,Picture3,Description);
                        movieList.add(citymovie);
                        mAdapter.notifyDataSetChanged();


                    }



                }


            } catch (JSONException | ParseException e) {
                e.printStackTrace();
            }
        }
    }

}

浩瀚星空 以前從沒想過null 竟然是這樣子~ 但經過這一次之後,我應該會儘量不使用null的方式~

通靈亡 iT邦研究生 5 級 ‧ 2020-08-03 14:12:13 檢舉

這邊邏輯感覺怪怪的:

if(Region.equals(name) & dt1.getTime() < dt2.getTime()) {
      (...省略...)
      if(name.length() <1) {}
}

如果資料的日期已過期,照理來說應該不會進入到 if(Region.equals(name) & dt1.getTime() < dt2.getTime())
那麼if(name.length() <1) 根本就不會有反應

另外,你的name是從intent帶過來的:

Intent intent = this.getIntent();
name = intent.getStringExtra("name");

想問name跟JSON的關係在哪邊?
這兩點是我看完比較疑惑的地方

通靈亡
name: 是由前一頁使用者按台北市的選項,把"台北市"這個值傳過來。
這時再將Json 的資料全部載入
再將name(台北市)這個值跟觀光局提供的json 裡面的 Region再做比對Region.equals(name),Region 跟name 兩者要等於,且日期不能是已過期的。

但不明白您這一句: "那麼if(name.length() <1) 根本就不會有反應"
因我的想法是:如果name 沒有東西,那它不是應該繼續執行下一行的程式嗎? 就是我最原本Toast.makeText(getApplication(), "小於1",
Toast.LENGTH_LONG).show();

還是我哪邊的想法不對?

通靈亡 iT邦研究生 5 級 ‧ 2020-08-03 15:03:31 檢舉

name: 是由前一頁使用者按台北市的選項,把"台北市"這個值傳過來。
再將name(台北市)這個值跟觀光局提供的json 裡面的 Region再做比對
因我的想法是:如果name 沒有東西,那它不是應該繼續執行下一行的程式嗎

你點出重點了
既然你的name是從前一頁帶過來的
那麼name不管如何都會有值吧

但不明白您這一句: "那麼if(name.length() <1) 根本就不會有反應"

你覺得當 if(Region.equals(name) & dt1.getTime() < dt2.getTime()) 不成立的時候,會執行到裡面的if(name.length() <1) 嗎?

// 條件符合的時候,將資料加到清單
if(Region.equals(name) & dt1.getTime() < dt2.getTime()){
    Log.i("Volley12", String.valueOf(sna.length()));
    
    citymovie citymovie = new citymovie(sna,Add,Start,End,Location,Picture1,px,py,Picture2,Picture3,Description);
    
    movieList.add(citymovie);
    mAdapter.notifyDataSetChanged();
}

依照你的程式碼
當符合條件,將資料加到movieList

如果說這個縣市完全沒資料
應該是for全部做完後,當 movieList.size() <= 0 的時候彈出toast才對吧

謝謝大家,謝謝通靈亡浩瀚星空 謝謝您們肯耐心的講解~ 讓我有再次的學習~

問題解決了,我留下我後面的程式碼,之後的人如果也遇到相同的問題,可以參考看看

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        JSONObject jonObject = null;

        try {
            jonObject = new JSONObject(s.toString());
            JSONArray contacts = jonObject.getJSONObject("XML_Head").getJSONObject("Infos").getJSONArray("Info");
            for (int i = 0; i < contacts.length(); i++) {
                JSONObject c = contacts.getJSONObject(i);
                String sna = c.getString("Name");
                String Region = c.getString("Region");
                String Add = c.getString("Add");
                String Start1 = c.getString("Start");
                String Location = c.getString("Location");
                String px = c.getString("Px");
                String py = c.getString("Py");
                String Description = c.getString("Description");

                String Start = Start1.substring(0,10);
                String Picture1 = c.getString("Picture1");
                String Picture2 = c.getString("Picture2");
                String Picture3 = c.getString("Picture3");
                String End1 = c.getString("End");
                String End = End1.substring(0,10);

              //  Log.i("Volley", sna);

                Calendar mCal = Calendar.getInstance();
                String dateformat = "yyyy-MM-dd";
                SimpleDateFormat df = new SimpleDateFormat(dateformat);
                String today = df.format(mCal.getTime());

                Date dt1 = df.parse(today);
                Date dt2 = df.parse(End);


                if(Region.equals(name) & dt1.getTime() < dt2.getTime()){

                    citymovie citymovie = new citymovie(sna,Add,Start,End,Location,Picture1,px,py,Picture2,Picture3,Description);
                    movieList.add(citymovie);
                    mAdapter.notifyDataSetChanged();



                }



            }
            if(movieList.size() >=1){
                Toast.makeText(getApplication(), "大於1",
                        Toast.LENGTH_LONG).show();
             //   Log.i("Volley12", String.valueOf(movieList));
            }else{
                Toast.makeText(getApplication(), "小於1",
                        Toast.LENGTH_LONG).show();
            }

        } catch (JSONException | ParseException e) {
            e.printStackTrace();
        }
    }
}

}

其實我java很少會用到null。且也寫的少。
但為了null的問題。
我曾經也為了javascript特別寫了一個isset跟isnull的判斷式來用。

浩瀚星空之前的想法會一直是,當資料抓不到,那它不就是null 或是empty 或是lenth =0,但程式碼不管怎麼試,就是沒動靜~ 但經過今天您這麼一說~ 之後可能會再對java更加的努力~

通靈亡 iT邦研究生 5 級 ‧ 2020-08-04 09:09:25 檢舉

Shihjoanna
總結來說,這次的問題算是程式邏輯上的錯誤,造成程式無法動作

在你的問題情境下,所謂的沒資料
應該是For迴圈過濾後,清單為空(筆數為0)的時候

因為你撈的每個JSON當中,Region欄位一定都會有值
而name是從前一頁帶過來,也一定都會有值
所以跟null其實沒有關係

之前我朋友也是弄了老半天,一直以為問題應該是A
後來幫他看完程式碼,最後才發現問題和A沒關係
算是程式不熟的人容易卡住的狀況,寫久就習慣了。

通靈亡

其實我昨天這個問題解決之後,原本我覺得理想的狀態是能希望能將「無資料顯示」能夠set在Recyclerview裡面,但沒有辦法解決,後來決定,當沒資料時,就用Toast顯示 + 再將頁面轉回前一頁。 但還是很謝謝您昨天的提點~

我要發表回答

立即登入回答