net.sf.json.JSONException: null object_json数组转json对象

net.sf.json.JSONException: null object_json数组转json对象1简介在程序开发过程中,在参数传递,函数返回值等方面,越来越多的使用JSON。JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,同时也易于机器解析和生成、易于理解、阅读和撰写,而且Json采用完全独立于语言的文本格式,这使得Json成为理想的数据交换语言。JSON建构于两种结构:“名称/值”对的集合(ACollectionofna…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

1 简介

在程序开发过程中,在参数传递,函数返回值等方面,越来越多的使用JSON。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,同时也易于机器解析和生成、易于理解、阅读和撰写,而且Json采用完全独立于语言的文本格式,这使得Json成为理想的数据交换语言。
JSON建构于两种结构:

  1. “名称/值”对的集合(A Collection of name/value pairs),在不同的语言中,它被理解为对象(Object), 记录(record), 结构(struct), 字典(dictionary), 有趣列表(keyed list), 哈希表(hash table)或者关联数组(associative array)。
  2. 值得有序列表(An order list of values)。在大多数语言中,它被理解为数组(array).
    在C++程序设计中,可以使用RapidJson、Jsoncpp等工具,因为才开始从事Java程序的开发,为了提升开发效率,因此也要熟练掌握一种Json生成和解析的工具。在Java中较为常见的Json解析工具有阿里巴巴的fastjson,但由于项目中自带有net.sf.json包。因此使用该包进行Json的构建和解析。

2 详细描述

JSON-lib是一个用于转换beans、maps、collections、java arrays、XML成JSON对象以及反之转化成benas和DynaBeans的java库。JSON-lib建立在Douglas Crockford的工作基础之上。

2.1 JSONObject

public final class JSONObject extends AbstractJSON implements JSON, Map, Comparable { 
   

从上述的接口声明中,可以看到JSONObject实现了接口Map,Comparable,这两个接口为java jdk自带的接口,而JSON接口代码如下:

package net.sf.json;
import java.io.Serializable;
import java.io.Writer;

public interface JSON extends Serializable { 
   
    boolean isArray();
    boolean isEmpty();
    int size();
    String toString(int var1);
    String toString(int var1, int var2);
    Writer write(Writer var1);
 }

一个JSONObject是一个无序的name/value对集合。它的外部形式是一个由花括号“{}”括起的字符串,在name和value之间使用冒号“:”隔开,在names/values之间用逗号隔开。JSONObjet的图示如下:
这里写图片描述
如下例所示:

{
    "errCode": 200,
    "msg": "success",
    "data": { "jguan": "11", "xming": "11", "dwei_name": "", "zji_code": "", "is_cbdwfzltxiu": "", "fzltxiu_date": "2", } }

内部的形式是一个拥有get和opt方法来根据name访问value、put方法来根据name增加或替换value的对象。在JSONObject中,值可以为以下类型:

Boolean、 JSONObject、 JSONArray、 NumberString、 或者JSONNull对象

JSONObject类型的构造器可以用于转换外部形式的JSON text成一种可以由get和opt方法访问的内部形式,或者使用element方法和toString方法把值转换成为JSON text。如果name存在,则get会返回对应的值,否则会抛出异常JSONException。而opt方法则会在不存在所要检索的name时可以指定一个默认值而不是抛出异常,这样可以获取可选择值。
普通的get()和opt()方法会返回Object,因而可以对返回值进行强制类型转换。也可以使用类型化的get和opt方法进行类型审核和强转。
String myString = new JSONObject().put(“JSON”, “Hello, World!”).toString();
将会产生{“JSON”: “Hello, World”}

2.2 JSONArray

JSONArray是一个有序的值得序列。它的外部形式是包括在方括号[]内的字符串,由逗号分隔值。

[“aaa”, “bbb”, “ccc”]

内部的形式是一个拥有get和opt方法的对象,这两个方法可以根据索引访问值,element方法可以用来添加和替换值。
这里写图片描述
这些值可以是任意类型

Boolean、 JSONObject、 JSONArray、 NumberString、 或者JSONNull对象

图示如下:
这里写图片描述
JSONArray的类型定义如下:

public final class JSONArray extends AbstractJSON implements JSON, List, Comparable { 
   

因此在操作JSONArray对象时可以使用JSON接口、List接口以及Comparable接口提供的方法,可以把JSONArray看成一个List对象。
构造器可以把一个JSON text转换成为Java对象,toString方法转换成JSON text。

3 如何安装

可以使用Maven快速导入该net.sf.json包,对应放入pom.xml依赖说明如下:

<dependency>
    <groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>

在pom.xml文件中添加上述的依赖,Import Changes即可。

注意:添加的依赖文件必须含有标记,不然maven无法从仓库中下载成功

4 JSONObject

4.1 构造器

JSONObject有两种常见的构造方法,一般常用的构造函数为JSONObject(),构造一个不含任何name/value的JSONObject对象

JSONObject
public JSONObject()
Construct an empty JSONObject. 

JSONObject
public JSONObject(boolean isNull)
Creates a JSONObject that is null. 

4.2 判断方法

由于JSONObject继承自Map接口,因此该类型自动的包含一些判断方法,简要介绍如下:

4.2.1 判空

判空的含义是JSONObject对象中是否不包含任何name/value对映射。

public boolean isEmpty()
Description copied from interface: JSON
Returns true if this object has no elements or keys. 
Specified by:
isEmpty in interface Map
Specified by:
isEmpty in interface JSON

<>4.2.2 判Null
判Null则对应构造函数的第二种形式,即该对象为null,而相应的在这类对象的基础上,如果添加了键值对,则会重新分配空间。

isNullObject
public boolean isNullObject()
Returs if this object is a null JSONObject. 

4.2.3 包含name

public boolean containsKey(uObject key)
Specified by:
containsKey in interface Map

该方法确保JSONObject中是否包含键的判断。
JSONObject对象也提供了has方法

public boolean has(String key)
Determine if the JSONObject contains a specific key. 
Parameters:
key - A key string. 
Returns:
true if the key exists in the JSONObject.

4.2.4 包含value

该接口继承自Map接口

public boolean containsValue(Object value)
Specified by:
containsValue in interface Map

4.2.5 判等

两个JSONObject对象相等表示两个JSONObject包含相同的键集合,同时每个键对应的值也相等。

public boolean equals(Object obj)
Specified by:
equals in interface Map
Overrides:
equals in class Object

4.2.6 判断是否为数组

判断一个name对应的value类型是否为数组的方法声明如下:

public boolean isArray()
Description copied from interface: JSON
Returns true if this object is a JSONArray, false otherwise. 
Specified by:
isArray in interface JSON

4.3 存储name/value

在JSONObject中可以存放name/value的方法有如下几种:accumulate方法、element方法、put方法、putAll方法、在此简要介绍这几个方法的用处。

4.3.1 追加

在JSONObject中由于name的类型为字符串类型,而值可以为JSONObject,JSONArray,Boolean、 JSONObject、 JSONArray、 Number、 String、 或者JSONNull对象。
在同一个name下,放置多个值,即组成JSONArray类型。
在下面的方法中,在一个key下累加一个值,如果已经有一个值为存储在key对应的对象中,该函数与element方法类似,此时会在key对应的位置存储一个JSONArray对象保存所有积累的值。如果已经有一个JSONArray对象,那么新值会追加到该JSONArray对象。作为对比,replace方法会替换之前的值。

public JSONObject accumulate(String key,
                             boolean value)
Accumulate values under a key. It is similar to the element method except that if there is already an object stored under the key then a JSONArray is stored under the key to hold all of the accumulated values. If there is already a JSONArray, then the new value is appended to it. In contrast, the replace method replaces the previous value. 
Parameters:
key - A key string.
value - An object to be accumulated under the key. 
Returns:
this.  
Throws: 
JSONException - If the value is an invalid number or if the key is null.

通过accumulate类方法可以把value累加到对应的name下而不会覆盖原有的value值而是形成一个JSONArray对象,不断追加新的Value。
类似的方法如下:

public JSONObject accumulate(String key, boolean value);
public JSONObject accumulate(String key, double value);
public JSONObject accumulate(String key, int value) ;
public JSONObject accumulate(String key, long value) ;
public JSONObject accumulate(String key, Object value);
public JSONObject accumulate(String key, Object value, JsonConfig jsonConfig) ;
public void accumulateAll(Map map);
public void accumulateAll(Map map, JsonConfig jsonConfig) ;

accumulate方法代码片段如下;

JSONArray array = new JSONArray();
array.add("123");
array.add(1);
Map<String, Integer> val = new HashMap<>();
val.put("1", 20);
val.put("2", 30);
System.out.println(array.toString());
array.add(val);
System.out.println(array.toString());

JSONObject json = new JSONObject(true);
System.out.println(json.isNullObject());
//Can't accumulate on null object
//json.accumulate("1", 1);
//null object
//json.put("1", 1);
json = new JSONObject();
json.accumulate("1", 1);
json.accumulate("1", val);
System.out.println(json.toString());
json.putAll(val);
System.out.println(json.toString());
打印结果如下:
["123",1]
["123",1,{
  
  "1":20,"2":30}]
true
{
  
  "1":[1,{
  
  "1":20,"2":30}]}
{
  
  "1":20,"2":30}

阅读上述代码片段,可以看到几个注意点:

注意:如果使用构造器new
JSONObject(true);则构造出来的JSONObject对象无法accumulate和put。否则会抛出异常,由代码片段中的注释可以看出。
另外put方法会进行替换而不会追加到name对应的value集合中。 最后的json.putAll(val); 中有name
“1”,替换了之前”1”对应的集合。

4.3.2 替换或存储

在JSONObject中替换name对应的value时,可以使用put方法实现

JSONObject json = new JSONObject();
SONArray jsonInner = new JSONArray();
//java.lang.IndexOutOfBoundsException: Index: 5, Size: 0
 //jsonInner.add(5, "1");
for(int i=0; i<5; i++) { 
   
     jsonInner.add(i);
}
json.put("1", jsonInner);
System.out.println(json.toString());
json.put("1", new int[]{
  
  1, 2, 6});
System.out.println(json.toString());
Map<String, String> vals = new HashMap<String, String>();
vals.put("1", "sqh");
vals.put("3", "lww");
vals.put("2", "computer");
json.putAll(vals);
System.out.println(json.toString());

向JSONObject对象中存储name/value对可以通过put存放。该接口继承自Map接口
当name已经存在于JSONObject中,实际作用是用新值替换旧值,与以下函数等价
json.replace(“1”, “sqh”);

4.3.3 存储

还有一类增加的方法为elemnent方法

public JSONObject element(String key,
                          double value)
Put a key/double pair in the JSONObject. 
Parameters:
key - A key string.
value - A double which is the value. 
Returns:
this. 
Throws: 
JSONException - If the key is null or if the number is invalid.

该类方法与put方法类似,但由于element方法的返回值类型为JSONObject,因此可以使用链式存储的方式,非常方便。
element方法代码片段如下:

JSONObject json = new JSONObject();
json.element("1", 1).element("2", 2);
System.out.println(json.toString());
json.element("1", 3).element("2", 4);
System.out.println(json.toString());

该代码片段运行结果如下:

{"1":1,"2":2}
{"1":3,"2":4}

从代码执行来看,第一次打印的值和第二次打印的值,分析得到实际执行取代了name ”1”和”2”的值。实际方法实现如下:

public JSONObject element(String key, int value) {
            this.verifyIsNull();
            return this.element(key, (Object)(new Integer(value)));
}

上述为JDK代码对应的代码实现,存放时转化为(Object)类型。

public JSONObject element(String key, boolean value) ;
public JSONObject element(String key, Collection value);
public JSONObject element(String key, Collection value, JsonConfig jsonConfig);
public JSONObject element(String key, double value) ;
public JSONObject element(String key, int value) ;
public JSONObject element(String key, long value);
public JSONObject element(String key, Map value) ;
public JSONObject element(String key, Map value, JsonConfig jsonConfig);
public JSONObject element(String key, Object value) ;
public JSONObject element(String key, Object value, JsonConfig jsonConfig) ;

4.4 检索

从JSONObject检索数据也提供了一些常用的方法,例如一些列的get方法,opt方法。介绍如下:

get
public Object get(Object key)
Specified by:
get in interface Map
________________________________________
get
public Object get(String key)
Get the value object associated with a key. 
Parameters:
key - A key string. 
Returns:
The object associated with the key. 
Throws: 
JSONException - if this.isNull() returns true.

4.4.1 getXXX

上述的两个方法第一个方法继承自Map接口,因此key的类型为Object,返回值类型也为Object,由于返回值类型为根类型,因此需要强制转换为具体的类型。

getBoolean
public boolean getBoolean(String key)
Get the boolean value associated with a key. 
Parameters:
key - A key string. 
Returns:
The truth. 
Throws: 
JSONException - if the value is not a Boolean or the String "true" or "false".

getBoolean方法如果key为null,或者值不是Boolean或者串”true”或”false”,会抛出JSONException异常。通过getXXX可以获取指定类型的Value而不需要强制转换,较为方便,
getBoolean方法实际实现如下:

public boolean getBoolean(String key) {
this.verifyIsNull();
Object o = this.get(key);
if (o != null) {
        if (o.equals(Boolean.FALSE) || o instanceof String && ((String)o).equalsIgnoreCase("false")) {
            return false;
        }

        if (o.equals(Boolean.TRUE) || o instanceof String && ((String)o).equalsIgnoreCase("true")) {
            return true;
        }
    }

    throw new JSONException("JSONObject[" + JSONUtils.quote(key) + "] is not a Boolean.");
}

同类型的方法如下:

public boolean getBoolean(String key) ;
public double getDouble(String key) {
this.verifyIsNull();
    Object o = this.get(key);
    if (o != null) {
        try {
            return o instanceof Number ? ((Number)o).doubleValue() : Double.parseDouble((String)o);
        } catch (Exception var4) {
            throw new JSONException("JSONObject[" + JSONUtils.quote(key) + "] is not a number.");
        }
    } else {
        throw new JSONException("JSONObject[" + JSONUtils.quote(key) + "] is not a number.");
    }
}

public int getInt(String key) ;
public JSONArray getJSONArray(String key) ;
public JSONObject getJSONObject(String key);
public long getLong(String key) ;
public String getString(String key) ;

4.4.2 optXXX

JSONObject同时提供了optXXX的方法获取name对应的value值。

public Object opt(String key) ;
public boolean optBoolean(String key) ;
public boolean optBoolean(String key, boolean defaultValue) ;
public double optDouble(String key) ;
public double optDouble(String key, double defaultValue);
public int optInt(String key) ;
public int optInt(String key, int defaultValue) ;
public JSONArray optJSONArray(String key) ;

public JSONObject optJSONObject(String key) {
    this.verifyIsNull();
    Object o = this.opt(key);
    return o instanceof JSONObject ? (JSONObject)o : null;
}

public long optLong(String key);
public long optLong(String key, long defaultValue) ;
public String optString(String key) ;
public String optString(String key, String defaultValue);

optXXX的方法与getXXX最大的区别是,optXXX方法可以指定默认值。

optDouble
public double optDouble(String key,
                        double defaultValue)
Get an optional double associated with a key, or the defaultValue if there is no such key or if its value is not a number. If the value is a string, an attempt will be made to evaluate it as a number. 
Parameters:
key - A key string.
defaultValue - The default. 
Returns:
An object which is the value.

4.5 遍历

在遍历JSONObject对象时,需要使用下述的方式。确保正确使用返回值,即迭代器或者Set集合,或者JSONArray

public Iterator keys()
Get an enumeration of the keys of the JSONObject. 
Returns:
An iterator of the keys.
public Set keySet()
Specified by:
keySet in interface Map
public JSONArray names()
Produce a JSONArray containing the names of the elements of this JSONObject. 
Returns:
A JSONArray containing the key strings, or null if the JSONObject is empty.
public Set entrySet()
Specified by:
entrySet in interface Map
public Collection values()
Specified by:
values in interface Map

使用上述方法的代码片段如下:

JSONObject json = new JSONObject();
json.element("1", new int[]{
  
  1, 2, 3}).element("2", (new JSONArray()).element(1).element(2));
json.element("3", 5.6);
json.element("4", "abc");
for (Object str:json.keySet()) {
     String key = (String)str;
     System.out.println(json.get(key));
}

Set<Object> ss = json.entrySet();
for (Object o:ss) {
     System.out.println(o);
}
Collection<Object> col = json.values();
System.out.println(col);
Iterator<Object> it = col.iterator();
while(it.hasNext()) {

    //取出迭代器对应的值
    System.out.println(it.next());
}

4.6 Map或Bean转换成JSONObject

//从一个Map构造JSONObject
Map map = new HashMap();
map.put( "name", "json" );
map.put( "bool", Boolean.TRUE );
map.put( "int", new Integer(1) );
map.put( "arr", new String[]{
  
  "a","b"} );
map.put( "func", "function(i){ return this.arr[i]; }" );
JSONObject jObject = JSONObject.fromObject( map );
System.out.println( jObject );
// prints ["name":"json","bool":true,"int":1,"arr":["a","b"],"func":func

从Bean转换为JSONObject

class MyBean{
        private String name = "json";
        private int pojoId = 1;
        private char[] options = new char[]{
  
  'a','f'};
        private String func1 = "function(i){ return this.options[i]; }";
        private JSONFunction func2 = new JSONFunction(new String[]{
  
  "i"},"return this.options[i];");
}
getset方法
//从一个Java对象(Java Bean构造JSONObject)
    JSONObject jsonObject = JSONObject.fromObject( new MyBean() );
    System.out.println( jsonObject );
/* prints
  {
  
  "name":"json","pojoId":1,"options":["a","f"],
  "func1":function(i){ return this.options[i];},
  "func2":function(i){ return this.options[i];}}
*/

5 代码演示

5.1 JSONObject

JSONObject的演示代码如下:
public class JSONObjectUse {

    public static void main(String[] args) {
        //创建JSONObject对象
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("username","wln");
        jsonObject.put("password","123");
        System.out.println("1:" + jsonObject);

        //增加属性
        jsonObject.element("sex","男");
        System.out.println("2:" + jsonObject);

        //判断输出对象的类型
        boolean isArray = jsonObject.isArray();
        boolean isEmpty = jsonObject.isEmpty();
        boolean isNullObject = jsonObject.isNullObject();
        System.out.println("3:" + "是否是数组:" + isArray +" 是否是空:" + isEmpty + " 是否是空对象:" + isNullObject);

        //创建JSONArray
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(0,"aa");
        jsonArray.add("BB");
        jsonArray.add(1,"AB");
        jsonArray.add("cc");

        //将JSONArray 添加到JSONObject
        jsonObject.element("student",jsonArray);
        System.out.println("4:" + jsonObject);
    }
}

结果:

1:{
  
  "username":"wln","password":"123"}
2:{
  
  "username":"wln","password":"123","sex":"男"}
3:是否是数组:false 是否是空:false 是否是空对象:false
4:{
  
  "username":"wln","password":"123","sex":"男","student":["aa","AB","BB","cc"]}

5.2 JSONArray

public class JSONArrayUse {

    public static void main(String[] args) {
        //创建JSONArray对象
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(0,"aa");
        jsonArray.add(1,"BB");
        jsonArray.element("cc");
        jsonArray.add("DD");
        System.out.println("1:" + jsonArray);
        //根据下标获取数据
        System.out.println("2:" + jsonArray.get(0));

        //根据下标设置数据
        jsonArray.set(0,"AAA");
        System.out.println("3:" + jsonArray);

        //创建JSONObject
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("username", "lwc");
        jsonObject.put("password", "123");
        //把JSONObject放入到JSONArray中
        jsonArray.add(jsonObject);
        System.out.println("4:" + jsonArray);

        //遍历
        System.out.println("5:");
        for(int i=0;i<jsonArray.size();i++){
            System.out.print(jsonArray.get(i)+"\t");
        }
    }
}

结果:

1:["aa","BB","cc","DD"]
2:aa
3:["AAA","BB","cc","DD"]
4:["AAA","BB","cc","DD",{
  
  "username":"lwc","password":"123"}]
5:
AAA    BB    cc    DD    {
  
  "username":"lwc","password":"123"}

5.3 Spring-MVC中用于参数接受

在使用JSONObject进行Java Web开发时,常用的便是json参数的解析和传送。在下述的代码片段中可以使用url进行访问:

url:localhost:8080/netjson?a=1&b=2

同时使用postman工具指定url Body为

{   "name":"sqh",    "pwd":"123",    "phone":1234 }

想要以一种非常方便的方式接受参数,则可以如下设置:

public JSONObject sfJsonTest(HttpServletRequest request, @RequestBody JSONObject content) {
  
  

通过指定@RequestBody类型为JSONObject,可以完成从JSON text到JSONObject的自动转换。

package com.example.demo;

import net.sf.json.JSONObject;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

@RestController
public class NetSfJsonTest {

    @ResponseBody
    @RequestMapping("/netsfjson")
    public JSONObject sfJsonTest(HttpServletRequest request, @RequestBody JSONObject content) {
        System.out.println("?后的内容: "+request.getQueryString());
        String name = (String)content.get("name");
        Integer phone = (Integer)content.get("phone");
        String pwd = (String)content.get("pwd");

        JSONObject result = new JSONObject();
        result.put("errCode", 200);
        result.put("errMsg", "success");
        result.put("data", content);

        return result;
    }
}

6 总结

由于在项目开发时必须以json的格式接受并且向前端以json的方式回传数据,因此比较熟悉某种json解析的方式非常有帮助。在C++开发时较为详细的了解了rapidJSON工具的使用,而Java开发时net.sf.json包的使用可以扮演同样的角色,熟练这个使用可以提升开发的效率。
文档位于

https://download.csdn.net/download/lk142500/10652591

7 引用

www.json.org/json-zh.html
https://www.cnblogs.com/nananana/p/9263708.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/190811.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号