Hi Why am i getting an inalid cast exception?
public class RootContainer2
{
[DataMember]
public string StopName { get; set; }
[DataMember]
public string StopId { get; set; }
[DataMember]
public string Stop { get; set; }
[DataMember]
public ObservableCollection<Stops> Stops { get; set; }
}
private void ContentPanel_Loaded(object sender, RoutedEventArgs e)
{
textRouteId.Text = this.NavigationContext.QueryString["name"];
string myvar = textRouteId.Text;
try
{
WebClient webClient = new WebClient();
Uri uri = new Uri("websiteurl");
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
webClient.OpenReadAsync(uri);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer ser = null;
try
{
ser = new DataContractJsonSerializer(typeof(RootContainer2));
RootContainer2 rootContainer = ser.ReadObject(e.Result) as RootContainer2;
foreach (Stops em in rootContainer.Stops)
{
string df = em.StopName;
string dt = em.StopId;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Here is the json output which I am trying to read but I get an invalid cast exception.
{"RouteId": "1231", "RouteName":"1 Whitehawk - Mile Oak", "Stops": [ { "StopId":"6882", "StopName":"Swanborough Drive", "OperatorsCode4":"bridmpj", "Lat":"50.8326729229821", "Lng":"-0.103217996656901" } , { "StopId":"6883", "StopName":"Haybourne Road", "OperatorsCode4":"brimapm", "Lat":"50.8317788816436", "Lng":"-0.10486427645364671" } , { "StopId":"6884", "StopName":"Coolham Drive", "OperatorsCode4":"brijtwm", "Lat":"50.829695439856089", "Lng":"-0.10512229365031489" } , { "StopId":"6885", "StopName":"St Cuthmans Church", "OperatorsCode4":"briapdg", "Lat":"50.8283233642578", "Lng":"-0.104808002710342" } ,
Plus the class in stops.cs :
public class Stops
{
public string StopId { get; set; }
public string StopName { get; set; }
}
EDIT:
So after creating my own url and then testing the data, it's something to do with the URL that I was given I think. Just doing further testing.
Edit 2
If i put the data into a text file and debug the data, it works if i do the following.
the end of the feed is like this:
"Lng":"-0.277833998203278", "" } ] }
If i remove the , and "" then it works. but how do i stop it getting there in the first place?
The exception could be caused by missing [DataContract] and [DataMember] attributes, in particular on the Stops class. With the exception of Silverlight 5, DataContract is an opt-in model where all classes and properties that should be serialized have to carry a explicit attribute.
Update:
After your comment, I've looked in more detail into the JSON data you receive. You provide two pieces of JSON. If combined, they look like this:
{
"RouteId": "1231",
"RouteName": "1 Whitehawk - Mile Oak",
"Stops": [
{
"StopId": "6882",
"StopName": "Swanborough Drive",
"OperatorsCode4": "bridmpj",
"Lat": "50.8326729229821",
"Lng": "-0.103217996656901"
},
{
"StopId": "6883",
"StopName": "Haybourne Road",
"OperatorsCode4": "brimapm",
"Lat": "50.8317788816436",
"Lng": "-0.10486427645364671"
},
{
"StopId": "6884",
"StopName": "Coolham Drive",
"OperatorsCode4": "brijtwm",
"Lat": "50.829695439856089",
"Lng": "-0.10512229365031489"
},
{
"StopId": "6885",
"StopName": "St Cuthmans Church",
"OperatorsCode4": "briapdg",
"Lat": "50.8283233642578",
"Lng": "-0.277833998203278",
""
}
]
}
I'm afraid this is simply invalid for JSON. As you found out yourself there is an extra comma and an extra emtpy pair of quotes close to the end. They make the difference between correct and invalid JSON. You can check it with an onlne JSON validator like JSONLint.
The best solution would be if you could fix it on the server side. Otherwise it's probably best to try to fix the data before you passed it into the serializer.
ReadObject() takes a Stream (or some XML-related types) but e.Result is of type object.
Try:
RootContainer2 rootContainer = ser.ReadObject((Stream)e.Result) as RootContainer2;
Edit: On second thoughts, that would probably throw an Invalid Parameter exception rather than an Invalid Cast.
Looks like the object being returned by ReadObject() is not castable to type RootContainer2.
Related
I'm still pretty new to programming with Kotlin but I can't seem to figure out the correct way to parse my JSON. I'm attempting to get "title" and "body" from "notification" in "unackd" array only.
So far I've got:
private fun parse(): Boolean {
try {
val ja = JSONArray(jsonData)
var jo: JSONObject
users.clear()
var user: User
for (i in 0 until ja.length()) {
jo = ja.getJSONObject(i)
val name = jo.getString("title")
val username = jo.getString("body")
user = User(username,name)
users.add(user)
}
return true
} catch (e: JSONException) {
e.printStackTrace()
return false
}
}
Meanwhile my JSON is structured as so:
{
"unackd": [
{
"notification": {
"title": "Title Test Number 200",
"body": "passage local they water difficulty tank industry allow increase itself captured strike immediately type phrase driver change save potatoes stems addition behavior grain trap rapidly love refused way television bright 1100"
},
"data": {
"id": "1100",
"phone": "+15555551234"
}
},
{
"notification": {
"title": "Title Test Number 199",
"body": "announced beside well noted mysterious farm he essential likely deeply vast touch 1099"
},
"data": {
"id": "1099",
"phone": "+15555551234"
}
}
],
"ackd": [
{
"notification": {
"title": "Title Test Number 200",
"body": "passage local they water difficulty tank industry allow increase itself captured strike immediately type phrase driver change save potatoes stems addition behavior grain trap rapidly love refused way television bright 1100"
},
"data": {
"id": "1100",
"phone": "+15555551234"
}
},
{
"notification": {
"title": "Title Test Number 199",
"body": "announced beside well noted mysterious farm he essential likely deeply vast touch 1099"
},
"data": {
"id": "1099",
"phone": "+15555551234"
}
}
]
}
I believe my issue is getting into "notification" to then get the strings "title" and "body". Which I've tried
test1 = jo.getJSONObject("notification")
Any help would be appreciated!
EDIT:
This is my logcat error, I assume it has to do with the JSON.typeMismatch:
at org.json.JSON.typeMismatch(JSON.java:111)
at org.json.JSONArray.<init>(JSONArray.java:96)
at org.json.JSONArray.<init>(JSONArray.java:108)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
The exception message suggests that you're passing data that doesn't represent a JSON array when instantiating JSONArray:
at org.json.JSON.typeMismatch(JSON.java:111)
at org.json.JSONArray.<init>(JSONArray.java:96)
The JSON you've attached is in fact a JSON object, notice that its content is enclosed in {}. Hence to access the "unackd" array, you need to first create a JSON object, and then reference the array inside of it:
val root = JSONObject(jsonData)
val ja = root.getJSONArray("unackd")
// the rest of your code goes here
Listen friend , parsing the JSON Object with JSON ARRAY with key (like: unackd , ackd) is so simple.
There are 2 ways:
1st Way)
Parse your JSON to Pojo schema
http://www.jsonschema2pojo.org/
public class Ackd {
#SerializedName("notification")
#Expose
private Notification_ notification;
#SerializedName("data")
#Expose
private Data_ data;
public Notification_ getNotification() {
return notification;
}
public void setNotification(Notification_ notification) {
this.notification = notification;
}
public Data_ getData() {
return data;
}
public void setData(Data_ data) {
this.data = data;
}
}
public class Data {
#SerializedName("id")
#Expose
private String id;
#SerializedName("phone")
#Expose
private String phone;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
No need to Make all class for parsing (like ackd (Json Array))
2nd Way)
You need to PARSE JSON array with name only unackd not ackd.
String jsonStr = sh.makeServiceCall(url);
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
JSONArray unA= jsonObj.getJSONArray("unackd");
for (int i = 0; i < unA.length(); i++)
{
JSONObject c = unA.getJSONObject(i);
String title= c.getString("title");
String body= c.getString("body");
}
Auto generate Data class
http://www.jsonschema2pojo.org/
I suppose that your class is named Response.java
Response object=new Gson().fromjson(jsonContentFile,Response.class);
Following data classes are generated for your JSON using https://json2kotlin.com
data class Json4Kotlin_Base (
val unackd : List<Unackd>,
val ackd : List<Ackd>
)
and
data class Data (
val id : Int,
val phone : Int
)
and
data class Notification (
val title : String,
val body : String
)
and
data class Ackd (
val notification : Notification,
val data : Data
)
and
data class Unackd (
val notification : Notification,
val data : Data
)
Here's a video that explains how to implement these when generated.
I am working in an graphql application where I have to send custom error object / message in json irrespective of whether it occurs in servlet or service.
Expected error response
{ errorCode: 400 //error goes here,
errorMessage: "my error mesage"}
It will be helpful if someone could guide me to achieve the above requirement.
GraphQL specification defines a clear format for the error entry in the response.
According to the spec, it should like this (assuming JSON format is used):
"errors": [
{
"message": "Name for character with ID 1002 could not be fetched.",
"locations": [ { "line": 6, "column": 7 } ],
"path": [ "hero", "heroFriends", 1, "name" ]
"extensions": {/* You can place data in any format here */}
}
]
So you won't find a GraphQL implementation that allows you to extend it and return some like this in the GraphQL execution result, for example:
"errors": [
{
"errorMessage": "Name for character with ID 1002 could not be fetched.",
"errorCode": 404
}
]
However, the spec lets you add data in whatever format in the extension entry. So you could create a custom Exception on the server side and end up with a response that looks like this in JSON:
"errors": [
{
"message": "Name for character with ID 1002 could not be fetched.",
"locations": [ { "line": 6, "column": 7 } ],
"path": [ "hero", "heroFriends", 1, "name" ]
"extensions": {
"errorMessage": "Name for character with ID 1002 could not be fetched.",
"errorCode": 404
}
}
]
It's quite easy to implement this on GraphQL Java, as described in the docs. You can create a custom exception that overrides the getExtensions method and create a map inside the implementation that will then be used to build the content of extensions:
public class CustomException extends RuntimeException implements GraphQLError {
private final int errorCode;
public CustomException(int errorCode, String errorMessage) {
super(errorMessage);
this.errorCode = errorCode;
}
#Override
public Map<String, Object> getExtensions() {
Map<String, Object> customAttributes = new LinkedHashMap<>();
customAttributes.put("errorCode", this.errorCode);
customAttributes.put("errorMessage", this.getMessage());
return customAttributes;
}
#Override
public List<SourceLocation> getLocations() {
return null;
}
#Override
public ErrorType getErrorType() {
return null;
}
}
then you can throw the exception passing in the code and message from inside your data fetchers:
throw new CustomException(400, "A custom error message");
Now, there is another way to tackle this.
Assuming you are working on a Web application, you can return errors (and data, for that matter) in whatever format that you want. Although that is a bit awkward in my opinion. GraphQL clients, like Apollo, adhere to the spec, so why would you want to return a response on any other format? But anyway, there are lots of different requirements out there.
Once you get a hold of an ExecutionResult, you can create a map or object in whatever format you want, serialise that as JSON and return this over HTTP.
Map<String, Object> result = new HashMap<>();
result.put("data", executionResult.getData());
List<Map<String, Object>> errors = executionResult.getErrors()
.stream()
.map(error -> {
Map<String, Object> errorMap = new HashMap<>();
errorMap.put("errorMessage", error.getMessage());
errorMap.put("errorCode", 404); // get the code somehow from the error object
return errorMap;
})
.collect(toList());
result.put("errors", errors);
// Serialize "result" and return that.
But again, having a response that doesn't comply with the spec doesn't make sense in most of the cases.
The other posted answer didn't work for me.
I found a solution by creating the following classes:
1) A throwable CustomException of GraphQLError type (just like mentioned in another answer).
2) Creating a GraphQLError Adaptor, which is not a Throwable.
3) A custom GraphQLErrorHandler to filter the custom exception.
Step 1:
The below throwable CustomGraphQLException implements GraphQLError because the GraphQLErrorHandler interface accepts errors only of type GraphQLError.
public class CustomGraphQLException extends RuntimeException implements GraphQLError {
private final int errorCode;
private final String errorMessage;
public CustomGraphQLException(int errorCode, String errorMessage) {
super(errorMessage);
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
#Override
public List<SourceLocation> getLocations() {
return null;
}
#Override
public ErrorType getErrorType() {
return null;
}
#Override
public String getMessage() {
return this.errorMessage;
}
#Override
public Map<String, Object> getExtensions() {
Map<String, Object> customAttributes = new HashMap<>();
customAttributes.put("errorCode", this.errorCode);
customAttributes.put("errorMessage", this.getMessage());
return customAttributes;
}
}
Step 2:
A non-throwable adaptor of GraphQLError is created to avoid the stack-trace of the above custom exception being passed in the final GraphQL Error Response.
public class GraphQLErrorAdaptor implements GraphQLError {
private final GraphQLError graphQLError;
public GraphQLErrorAdaptor(GraphQLError graphQLError) {
this.graphQLError = graphQLError;
}
#Override
public List<SourceLocation> getLocations() {
return graphQLError.getLocations();
}
#Override
public ErrorType getErrorType() {
return graphQLError.getErrorType();
}
#Override
public String getMessage() {
return graphQLError.getMessage();
}
#Override
public Map<String, Object> getExtensions() {
return graphQLError.getExtensions();
}
}
Step 3:
A custom GraphQLErrorHandler is implemented to filter the custom CustomGraphQLException and avoid its replacement with the default graphQL error response.
public class CustomGraphQLErrorHandler implements GraphQLErrorHandler {
public CustomGraphQLErrorHandler() { }
public List<GraphQLError> processErrors(List<GraphQLError> errors) {
List<GraphQLError> clientErrors = this.filterGraphQLErrors(errors);
List<GraphQLError> internalErrors = errors.stream()
.filter(e -> isInternalError(e))
.map(GraphQLErrorAdaptor::new)
.collect(Collectors.toList());
if (clientErrors.size() + internalErrors.size() < errors.size()) {
clientErrors.add(new GenericGraphQLError("Internal Server Error(s) while executing query"));
errors.stream().filter((error) -> !this.isClientError(error)
).forEach((error) -> {
if (error instanceof Throwable) {
LOG.error("Error executing query!", (Throwable) error);
} else {
LOG.error("Error executing query ({}): {}", error.getClass().getSimpleName(), error.getMessage());
}
});
}
List<GraphQLError> finalErrors = new ArrayList<>();
finalErrors.addAll(clientErrors);
finalErrors.addAll(internalErrors);
return finalErrors;
}
protected List<GraphQLError> filterGraphQLErrors(List<GraphQLError> errors) {
return errors.stream().filter(this::isClientError).collect(Collectors.toList());
}
protected boolean isClientError(GraphQLError error) {
return !(error instanceof ExceptionWhileDataFetching) && !(error instanceof Throwable);
}
protected boolean isInternalError(GraphQLError error) {
return (error instanceof ExceptionWhileDataFetching) &&
(((ExceptionWhileDataFetching) error).getException() instanceof CustomGraphQLException);
}
}
Step 4:
Configure the CustomGraphQLErrorHandler in GraphQLServlet. I am assuming you are using spring-boot for this step.
#Configuration
public class GraphQLConfig {
#Bean
public ServletRegistrationBean graphQLServletRegistrationBean(
QueryResolver queryResolver,
CustomGraphQLErrorHandler customGraphQLErrorHandler) throws Exception {
GraphQLSchema schema = SchemaParser.newParser()
.schemaString(IOUtils.resourceToString("/library.graphqls", Charset.forName("UTF-8")))
.resolvers(queryResolver)
.build()
.makeExecutableSchema();
return new ServletRegistrationBean(new SimpleGraphQLServlet(schema,
new DefaultExecutionStrategyProvider(), null, null, null,
customGraphQLErrorHandler, new DefaultGraphQLContextBuilder(), null,
null), "/graphql");
}
}
Reference
I'm looking for help in de-serializing a JSON to an instance of its POJO. The top level POJO Graph.java has an attribute of type HashMap. While serializing it throws
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line n column nn path
$.degreesCountMap[0]
I know exactly what it means and how to fix it for for a top level collection but not sure how to specify the Type for an attribute of a another object.
I did review discussions on such issues in this and many other forums but I don't really see an answer that can help me.
I would greatly appreciate any help on this.
Here's the JSON of Graph:
{
"nodeCount":3,
"edgeCount":2,
"degreesCountMap":[
{
"ONE":2
},
{
"TWO":1
}
],
"nodes":[
{
"index":0,
"connectedIndices":[
1
]
},
{
"index":1,
"connectedIndices":[
0,
2
]
},
{
"index":2,
"connectedIndices":[
1
]
}
]
}
Here are the POJOs
Graph.java
public class Graph {
private HashMap<Degree, Integer> degreesCountMap;
private Integer edgeCount;
private Integer nodeCount;
private ArrayList<Node> nodes;
public HashMap<Degree, Integer> getDegreesCountMap() {
return degreesCountMap;
}
public void setDegreesCountMap(HashMap<Degree, Integer> degreesCountMap) {
this.degreesCountMap = degreesCountMap;
}
public void setNodes(ArrayList<Node> nodes) {
this.nodes = nodes;
}
}
Degree.java
public enum Degree {
ZERO, ONE, THREE, FOUR;
}
Node.java
public class Node {
private ArrayList<Integer> connectedIndices;
private int index;
public ArrayList<Integer> getConnectedIndices() {
return connectedIndices;
}
public int getIndex() {
return index;
}
public void setConnectedIndices(ArrayList<Integer> connectedIndices) {
this.connectedIndices = connectedIndices;
}
public void setIndex(int index) {
this.index = index;
}
}
GraphTest.java
#Test
public void testJsonToGraph() {
String json = "{\"nodeCount\":3,\"edgeCount\":2,"
+ "\"degreesCountMap\":[{\"ONE\":2},{\"TWO\":1}],"// <--to fail
+ "\"nodes\":[{\"index\":0,\"connectedIndices\":[1]},"
+ "{\"index\":1,\"connectedIndices\":[0,2]},"
+ "{\"index\":2,\"connectedIndices\":[1]}]}";
try {
graph = gson.fromJson(json, Graph.class);
assertNotNull(graph);
} catch (Exception e) { // Intentionally capturing to diagnose
e.printStackTrace();
}
}
The problem is that the JSON you posted is not valid.
Because Map can be used to map any object to any object Gson have to make map as array with two objects.
The valid JSON for map object would looks like this:
"degreesCountMap": [
[
"ONE",
2
],
[
"TWO",
1
]
]
but since you are using enum as keys the following code is also valid:
"degreesCountMap": {
"TWO": 1,
"ONE": 2
}
Solution: edit your json to valid one. Also, I think you are missing TWO in your degree enum.
Note: Because you use enum there is just "ONE" but if you used a typical object for a key it could looks like this:
"degreesCountMap": [
[
{ "degree": "ONE" },
2
],
[
{ "degree": "TWO" },
1
]
]
I have an object with predefined data structure:
public class A
{
public string Id {get;set;}
public bool? Enabled {get;set;}
public int? Age {get;set;}
}
and JSON is supposed to be
{ "Id": "123", "Enabled": true, "Age": 23 }
I want to handle JSON error in positive way, and whenever server returns unexpected values for defined data-types I want it to be ignore and default value is set (null).
Right now when JSON is partially invalid I'm getting JSON reader exception:
{ "Id": "123", "Enabled": "NotABoolValue", "Age": 23 }
And I don't get any object at all.
What I want is to get an object:
new A() { Id = "123", Enabled = null, Age = 23 }
and parsing warning if possible.
Is it possible to accomplish with JSON.NET?
To be able to handle deserialization errors, use the following code:
var a = JsonConvert.DeserializeObject<A>("-- JSON STRING --", new JsonSerializerSettings
{
Error = HandleDeserializationError
});
where HandleDeserializationError is the following method:
public void HandleDeserializationError(object sender, ErrorEventArgs errorArgs)
{
var currentError = errorArgs.ErrorContext.Error.Message;
errorArgs.ErrorContext.Handled = true;
}
The HandleDeserializationError will be called as many times as there are errors in the json string. The properties that are causing the error will not be initialized.
Same thing as Ilija's solution, but a oneliner for the lazy/on a rush (credit goes to him)
var settings = new JsonSerializerSettings { Error = (se, ev) => { ev.ErrorContext.Handled = true; } };
JsonConvert.DeserializeObject<YourType>(yourJsonStringVariable, settings);
Props to Jam for making it even shorter =)
There is another way. for example, if you are using a nuget package which uses newton json and does deseralization and seralization for you. You may have this problem if the package is not handling errors. then you cant use the solution above. you need to handle in object level. here becomes OnErrorAttribute useful. So below code will catch any error for any property, you can even modify within the OnError function and assign default values
public class PersonError
{
private List<string> _roles;
public string Name { get; set; }
public int Age { get; set; }
public List<string> Roles
{
get
{
if (_roles == null)
{
throw new Exception("Roles not loaded!");
}
return _roles;
}
set { _roles = value; }
}
public string Title { get; set; }
[OnError]
internal void OnError(StreamingContext context, ErrorContext errorContext)
{
errorContext.Handled = true;
}
}
see https://www.newtonsoft.com/json/help/html/SerializationErrorHandling.htm
I need to read the following piece of code using RestSharp. My problem is how to get the array in the proper structure. How do I need to setup the class that will contain the object to make this work properly?
I would like to deserialize the object "0" and "1" in a List of type AcUserInfo.
Thanks a lot.
Andrea
{
"0":{
"id":"2",
"subscriberid":"2",
"cdate":"2012-09-28 16:49:06",
"sdate":"2012-09-28 16:49:06",
"first_name":"Al",
"last_name":"",
"email":"test#verizon.net"
},
"1":{
"id":"29",
"subscriberid":"29",
"cdate":"2012-10-02 15:08:29",
"sdate":"2012-10-02 15:08:29",
"first_name":"Mark",
"last_name":"",
"email":"test2#verizon.net"
},
"result_code":1,
"result_message":"Success: Something is returned",
"result_output":"json"
}
Here's the class I've created:
public class SubscriberList {
public int result_code { get; set; }
public string result_message { get; set; }
public string result_output { get; set; }
public List<AcUserInfo> row { get; set; }
SubscriberList(){
row = new List<AcUserInfo>();
}
}
Your JSON data does not contain an array, and therefore cannot be deserialized to a List<>.
Either convert your JSON to something like this:
{
[{
"id":"2",
"subscriberid":"2",
"cdate":"2012-09-28 16:49:06",
"sdate":"2012-09-28 16:49:06",
"first_name":"Al",
"last_name":"",
"email":"test#verizon.net"
},
{
"id":"29",
"subscriberid":"29",
"cdate":"2012-10-02 15:08:29",
"sdate":"2012-10-02 15:08:29",
"first_name":"Mark",
"last_name":"",
"email":"test2#verizon.net"
}],
"result_code":1,
"result_message":"Success: Something is returned",
"result_output":"json"
}
Or if you always only have the "0" & "1" element then change your SubscriberList class to match it.