简体   繁体   中英

IllegalStateException during the parsing of Json in RealmDatabase

I use data base Realm, I have a json object, which I need to parse from the file and save to the data base.

  {
    "pPID": 1,
    "pName": "myName",
    "pDesc": "myDescription",
    "pTotal": 120,
    "pOrder": 1,
    "puoCompleted": false,
    "puoProgressPercent":0,
    "puoProgressCount":0,
    "pCommercialAccessRule": {
      "tag": "myTag",
      "contents": [
        "string object", "string object"
      ]
    }
  }

Problem appears in the object pCommercialAccessRulle, in which we have a list of string, primitive types are not supported, that's why I created an object.

public class RealmString extends RealmObject{

    String string;

    public String getString() {
        return string;
    }

    public void setString(String string) {
        this.string = string;
    }
}

In the class CommercialAccessRule I created list not of the strings, but of the objects RealmString

public class CommercialAccessRule extends RealmObject implements Serializable {


    private String tag;
    private RealmList<RealmString> contents;

    public CommercialAccessRule() {
    }

    public String getTag() {
        return tag;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }

    public RealmList<RealmString> getContents() {
        return contents;
    }

    public void setContents(RealmList<RealmString> contents) {
        this.contents = contents;
    }

}

but I get such an error

Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
at android.util.JsonReader.expect(JsonReader.java:310) at android.util.JsonReader.beginObject(JsonReader.java:293)
at io.realm.RealmStringRealmProxy.createUsingJsonStream(RealmStringRealmProxy.java:136) at io.realm.CommercialAccessRuleRealmProxy.createUsingJsonStream(CommercialAccessRuleRealmProxy.java:390) at io.re    
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRINGalm.PDataRealmProxy.createUsingJsonStream(PDataRealmProxy.java:525) at io.realm.DefaultRealmModuleMediator.createUsingJsonStream(DefaultRealmModuleMediator.java:257) at io.realm.Realm.createAllFromJson(Realm.java:435)

after the searching I get there and then there , but can't understand how to implement it here:

InputStream stream = null;
    try {
        stream = getApplicationContext().getAssets().open("test_pdata.json");
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        realm.beginTransaction();
        realm.createAllFromJson(PData.class, stream);
        realm.commitTransaction();
    } catch (IOException e) {
        realm.cancelTransaction();
    } finally {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

Here is the class PDate, json of which I wrote above.

public class PData extends RealmObject implements Serializable{

    private static final String TAG = PData.class.getSimpleName();

    private String pName;
    private String pDesc;
    private boolean puoCompleted;
    private int pPID;
    private int pTotal;
    private int pOrder;
    private  int puoProgressCount;
    private int puoProgressPercent;
    private CommercialAccessRule pCommercialAccessRule;
    private String originalJson;

    public PData() {
    }


    public String getpName() {
        return pName;
    }

    public void setpName(String pName) {
        this.pName = pName;
    }

    public String getpDesc() {
        return pDesc;
    }

    public void setpDesc(String pDesc) {
        this.pDesc = pDesc;
    }

    public boolean ispuoCompleted() {
        return puoCompleted;
    }

    public void setpuoCompleted(boolean puoCompleted) {
        this.puoCompleted = puoCompleted;
    }

    public int getpPID() {
        return pPID;
    }

    public void setpPID(int pPID) {
        this.pPID = pPID;
    }

    public int getpTotal() {
        return pTotal;
    }

    public void setpTotal(int pTotal) {
        this.pTotal = pTotal;
    }

    public int getpOrder() {
        return pOrder;
    }

    public void setpOrder(int pOrder) {
        this.pOrder = pOrder;
    }

    public int getpuoProgressCount() {
        return puoProgressCount;
    }

    public void setpuoProgressCount(int puoProgressCount) {
        this.puoProgressCount = puoProgressCount;
    }

    public int getPuoProgressPercent() {
        return puoProgressPercent;
    }

    public void setPuoProgressPercent(int puoProgressPercent) {
        this.puoProgressPercent = puoProgressPercent;
    }

    public CommercialAccessRule getCommercialAccessRule() {
        return pCommercialAccessRule;
    }

    public void setpCommercialAccessRule(CommercialAccessRule pCommercialAccessRule) {
        this.pCommercialAccessRule = pCommercialAccessRule;
    }

    public String getOriginalJson() {
        return originalJson;
    }

    public void setOriginalJson(String originalJson) {
        this.originalJson = originalJson;
    }




    @Override
    public String toString() {
        return "PData{" +
                "pName='" + pName + '\'' +
                ", pDesc='" + pDesc + '\'' +
                ", puoCompleted=" + puoCompleted +
                ", pPID=" + pPID +
                ", pTotal=" + pTotal +
                ", pOrder=" + pOrder +
                ", puoProgressCount=" + puoProgressCount +
                ", puoProgressPercent=" + puoProgressPercent +
                ", pCommercialAccessRule=" + pCommercialAccessRule +
                ", originalJson='" + originalJson + '\'' +
                '}';
    }

}

follow this Steps:

  1. after you get the JsonResponse, pass the response Object as a parameter to JsonHelper Class by calling the method " toMap(your_jsonResponse_object) ".

  2. JsonHelper class converts JsonObject to map.

  3. map contains key value (it may contains arraylist also), based on the key you will get the value.

4.update your realm object with the value you get.

// sorry for my bad explanation.

//using this class you can convert json data

copied from https://gist.github.com/codebutler/2339666

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.*;

public class JsonHelper {
public static Object toJSON(Object object) throws JSONException {
    if (object instanceof Map) {
        JSONObject json = new JSONObject();
        Map map = (Map) object;
        for (Object key : map.keySet()) {
            json.put(key.toString(), toJSON(map.get(key)));
        }
        return json;
    } else if (object instanceof Iterable) {
        JSONArray json = new JSONArray();
        for (Object value : ((Iterable)object)) {
            json.put(value);
        }
        return json;
    } else {
        return object;
    }
}

public static boolean isEmptyObject(JSONObject object) {
    return object.names() == null;
}

public static Map<String, Object> getMap(JSONObject object, String key) throws JSONException {
    return toMap(object.getJSONObject(key));
}

public static Map<String, Object> toMap(JSONObject object) throws JSONException {
    Map<String, Object> map = new HashMap();
    Iterator keys = object.keys();
    while (keys.hasNext()) {
        String key = (String) keys.next();
        map.put(key, fromJson(object.get(key)));
    }
    return map;
}

public static List toList(JSONArray array) throws JSONException {
    List list = new ArrayList();
    for (int i = 0; i < array.length(); i++) {
        list.add(fromJson(array.get(i)));
    }
    return list;
}

private static Object fromJson(Object json) throws JSONException {
    if (json == JSONObject.NULL) {
        return null;
    } else if (json instanceof JSONObject) {
        return toMap((JSONObject) json);
    } else if (json instanceof JSONArray) {
        return toList((JSONArray) json);
    } else {
        return json;
     }
  }
}

// in activity pass jsonObject to above class, you will get Map/Arraylist

public class MainActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

   Map<String,Object> convertedData = new HashMap<>();
   // pass the jsonResponse to JsonHelperClass
    convertedData = toMap(jsonObject);

    //upadte your realm object
    your_realm_object.updateWithJsonData(convertedData);

     }
 }

 //realmObject class
public YourRealm extends RealmObject{

 String name;
 String id;
 String desc;
// setters and getters

//update realm Object with json data
 public void updateWithJsonData(Map<String,Object> data){

  setName(data.get("pName"));
  setId(data.get("pPID"));
  //......
  }
}

If you want to create JSON Object for your element Use GSON. for that.

Fox ex :

RealmObject obj  = new RealmObject();
obj.setpPID(1);
obj.setpName("myName");
obj.setpDesc(myDescription");
obj.setpTotal(120);
obj.setpOrder(1);
obj.setpuoCompleted(false);
obj.setpuoProgressPercent(0);
obj.setpuoProgressCount(0);
CommercialAccessRule innerobj = new CommercialAccessRule();
innerobj.setTag("myTag");
List<String> strList = new ArrayList<>();
strList.add("string object");
strList.add("string object");
obj.setpCommercialAccessRule(innerobj);
Gson gson = new Gson();
String JSONString = gson.toJson(obj);
RealmObject obj1 = gson.fromJson(JSONString,RealmObject.class);

Result of JSONString will be

{"pPID":1,"pName":"myName","pDesc":"myDescription","pTotal":120,"pOrder":1,"puoCompleted":false,"puoProgressPercent":0,"puoProgressCount":0,"pCommercialAccessRule":{"tag":"myTag","contents":["string object","string object"]}}

Use this for validating yourJSON : https://jsonformatter.curiousconcept.com/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM