I'm trying to parse JSON string that received from websocket sharp but keep failing.
using (var ws = new WebSocket(WebAddr))
{
ws.Log.Level = LogLevel.Debug;
ws.OnOpen += (ss, ee) =>
{
System.IO.File.WriteAllText(#"C:\log.txt", "connected!");
};
ws.OnMessage += (ss, ee) =>
{
JsonValue jo = JsonValue.Parse(ee.Data);
string value = (string)jo["levelid"];
Console.Write(value + '\n');
};
}
It just threw exception error when reaches string value... part.
I'm using System.Json from nuget.
I think I figured it out. The server will respond with 2 messages, one is Json object and one is Json array.
dynamic jo = JsonConvert.DeserializeObject(ee.Data);
This fixed my problem!
Related
I'm trying out things with Flutter right now. But my variables keep getting reinitialised when accessed from another class.
I'm using json parsing and i need two parts of my request. The "Relatorio" part and the "Mensagem" part.
to parse this json i'm doing this:
List<RelatorioProdutos> parseRelatorioPorProduto(String responseBody) {
final parsed = json.decode(responseBody);
var relatorio = parsed['Relatorio'];
var mensagem = parsed['Mensagem'];
print (mensagem); // Here the variable returns well,
//but when i need it in other class i receive null.
return relatorio.map<RelatorioProdutos>((json) => new RelatorioProdutos.fromJson(json)).toList();
}
class RelatorioProdutos {
String CodigoProduto;
var QtdVendida;
var TotalVendas;
String Descricao;
RelatorioProdutos({this.CodigoProduto, this.QtdVendida, this.TotalVendas, this.Descricao,});
factory RelatorioProdutos.fromJson(Map json) {
//returns a List of Maps
return new RelatorioProdutos(
CodigoProduto: json['CodigoProduto'] as String,
QtdVendida: json['QtdVendida'],
TotalVendas: json['TotalVendas'],
Descricao: json['Descricao'] as String,
);
}
}
I want to use this 'mensagem' variable in another class to show the error for user, but i always receive 'null'.
i already tried setState but it reloads my json and i dont want to request the RestServer again.
Thanks from now!
If I understand correctly, you want to access a local variable of a function from another class. I don't think it's possible.
One way to do it, would be to wrap your response in another object containing the response, and this variable:
List<Response<RelatorioProdutos>> parseRelatorioPorProduto(
String responseBody) {
final parsed = json.decode(responseBody);
var relatorio = parsed['Relatorio'];
var mensagem = parsed['Mensagem'];
print(mensagem); // Here the variable returns well,
//but when i need it in other class i receive null.
return relatorio
.map((json) => new Response<RelatorioProdutos>(
new RelatorioProdutos.fromJson(json), mensagem))
.toList();
}
class RelatorioProdutos {
String CodigoProduto;
var QtdVendida;
var TotalVendas;
String Descricao;
RelatorioProdutos({
this.CodigoProduto,
this.QtdVendida,
this.TotalVendas,
this.Descricao,
});
factory RelatorioProdutos.fromJson(Map json) {
//returns a List of Maps
return new RelatorioProdutos(
CodigoProduto: json['CodigoProduto'] as String,
QtdVendida: json['QtdVendida'],
TotalVendas: json['TotalVendas'],
Descricao: json['Descricao'] as String,
);
}
}
class Response<T> {
const Response(
this.value,
this.errorMessage,
);
final T value;
final String errorMessage;
bool get hasError => errorMessage != null;
}
In this example I created a Response object that can contains both the response value and an error message.
In the parseRelatorioPorProduto, instead of returning the relatorio, I changed the return type to Response<RelatorioProdutos> in order to have access to the value and the error message from any class which call this function.
Thanks Letsar, i tried yout ideia but i get a lot of others erros.
To solve this problem i used this:
List<RelatorioProdutos> parseRelatorioPorProduto(String responseBody) {
final parsed = json.decode(responseBody);
var relatorio = parsed['Relatorio'];
var mensagem = parsed['Mensagem'];
if(mensagem[0].toString().substring(16,17) == "0"){
List<RelatorioProdutos> asd = new List();
RelatorioProdutos aimeudeus = new RelatorioProdutos(Descricao: mensagem[0].toString(), CodigoProduto: "a", TotalVendas: 0, QtdVendida: 0);
asd.add(aimeudeus);
return asd;
}else{
return relatorio.map<RelatorioProdutos>((json) => new RelatorioProdutos.fromJson(json)).toList();
}
}
I was able to solve this solution is in the coment
I have problem with parsing data that I get rom Facebook on appRequestCallback.
The request is send and that part is ok. But I need to pars the send data for the internal uses.
the code is this
private void appRequestCallback(FBResult result)
{
Util.Log("appRequestCallback");
if (result != null)
{
var responseObject = Json.Deserialize(result.Text) as Dictionary<string, object>;
object obj = 0;
string resp = (string)responseObject["request"];
Util.Log ("resp : " + resp);
if (responseObject.TryGetValue("cancelled", out obj))
{
Util.Log("Request cancelled");
}
else if (responseObject.TryGetValue("request", out obj))
{
responseObject.TryGetValue("to", out obj);
string[] s = (string[]) obj;
Util.Log ("s: " + s);
AddPopupMessage("Request Sent", ChallengeDisplayTime);
Util.Log("Request sent");
}
}
}
In the console I get this
appRequestCallback
UnityEngine.Debug:Log(Object)
resp: 870884436303337
UnityEngine.Debug:Log(Object)
And then the error
InvalidCastException: Cannot cast from source type to destination type.
MainMenu.appRequestCallback (.FBResult result) (at Assets/Resources/Scripts/MainMenu.cs:482)
Facebook.AsyncRequestDialogPost.CallbackWithErrorHandling (.FBResult result)
Facebook.AsyncRequestString+c__Iterator0.MoveNext ()
The problem is in parsing of to: part of json file and I am not sure why. I have tried to cast it into string, string[], List<>, Array, ArrayList. As I see the problem is that I am not using the good cast type for the to: but I can not figure out what the correct cast type is
I am using REST service to get the data from the Db.
In my class, I am having the property "UploadTime" of datatype TimeSpan?.
The time span is calculated based on the difference between dates and in the response,I ma getting response as :
ArrayOfUploadUI xmlns="http://schemas.datacontract.org/2004/07/NMS.ApplicationService.HIM.Objects" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<UploadUI>
<UID>1</UID>
<DateCompleted>2015-01-08T10:46:25.25</DateCompleted>
<DateNotified>2015-01-07T10:46:25.25</DateNotified>
<DateDictationStartTime i:nil="true" />
<DateDictationEndTime i:nil="true" />
<UploadTime>P1D</UploadTime>
<ExistsOnBackend>false</ExistsOnBackend>
</UploadUI>
</ArrayOfUploadUI>
.
I am getting the following exception while trying to get the data:
using (HttpResponseMessage response = await _HttpClient(session).GetAsync(apiUrl))
{
if (response.IsSuccessStatusCode)
result = await response.Content.ReadAsAsync<T>();
else
await _HandleInvalidResponseAsync(response);
}
I am getting issue at the "response.Content.ReadAsAsync();".
Error is:
Error converting value "P1D" to type 'System.Nullable`1[System.TimeSpan]'. Path '[0].UploadTime', line 1, position 518.
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType).
I googled and I came to know that WCF serilaizing the "timeSpan"datatype from "1:0:0:00" to "P1D".
My issue is how to deserialize this on the response level.
I have done formatting for the date at the source level and the issue got resolved.
JsonSerializerSettings dateFormatSettings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
};
string jsonNMSPlatformObject = JsonConvert.SerializeObject(nmsPlatformObject,dateFormatSettings);
using (HttpContent httpContent = new StringContent(jsonNMSPlatformObject))
{
httpContent.Headers.ContentType = new MediaTypeHeaderValue(JsonMedaType);
var request = new HttpRequestMessage(HttpMethod.Delete, apiUrl);
request.Content = httpContent;
using (HttpResponseMessage response = await _HttpClient(session).SendAsync(request))
{
if (response.IsSuccessStatusCode)
return;
else
await _HandleInvalidResponseAsync(response, jsonNMSPlatformObject);
}
}
I have a file that contains a json array of objects:
[
{
"test1": "abc"
},
{
"test2": [1, 2, 3]
}
]
I wish to use use Jackson's JsonParser to take an inputstream from this file, and at every call to .next(), I want it to return an object from the array until it runs out of objects or fails.
Is this possible?
Use case:
I have a large file with a json array filled with a large number of objects with varying schemas. I want to get one object at a time to avoid loading everything into memory.
EDIT:
I completely forgot to mention. My input is a string that is added to over time. It slowly accumulates json over time. I was hoping to be able to parse it object by object removing the parsed object from the string.
But I suppose that doesn't matter! I can do this manually so long as the jsonParser will return the index into the string.
Yes, you can achieve this sort of part-streaming-part-tree-model processing style using an ObjectMapper:
ObjectMapper mapper = new ObjectMapper();
JsonParser parser = mapper.getFactory().createParser(new File(...));
if(parser.nextToken() != JsonToken.START_ARRAY) {
throw new IllegalStateException("Expected an array");
}
while(parser.nextToken() == JsonToken.START_OBJECT) {
// read everything from this START_OBJECT to the matching END_OBJECT
// and return it as a tree model ObjectNode
ObjectNode node = mapper.readTree(parser);
// do whatever you need to do with this object
}
parser.close();
What you are looking for is called Jackson Streaming API. Here is a code snippet using Jackson Streaming API that could help you to achieve what you need.
JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createJsonParser(new File(yourPathToFile));
JsonToken token = parser.nextToken();
if (token == null) {
// return or throw exception
}
// the first token is supposed to be the start of array '['
if (!JsonToken.START_ARRAY.equals(token)) {
// return or throw exception
}
// iterate through the content of the array
while (true) {
token = parser.nextToken();
if (!JsonToken.START_OBJECT.equals(token)) {
break;
}
if (token == null) {
break;
}
// parse your objects by means of parser.getXxxValue() and/or other parser's methods
}
This example reads custom objects directly from a stream:
source is a java.io.File
ObjectMapper mapper = new ObjectMapper();
JsonParser parser = mapper.getFactory().createParser( source );
if ( parser.nextToken() != JsonToken.START_ARRAY ) {
throw new Exception( "no array" );
}
while ( parser.nextToken() == JsonToken.START_OBJECT ) {
CustomObj custom = mapper.readValue( parser, CustomObj.class );
System.out.println( "" + custom );
}
This is a late answer that builds on Ian Roberts' answer. You can also use a JsonPointer to find the start position if it is nested into a document. This avoids custom coding the slightly cumbersome streaming token approach to get to the start point. In this case, the basePath is "/", but it can be any path that JsonPointer understands.
Path sourceFile = Paths.get("/path/to/my/file.json");
// Point the basePath to a starting point in the file
JsonPointer basePath = JsonPointer.compile("/");
ObjectMapper mapper = new ObjectMapper();
try (InputStream inputSource = Files.newInputStream(sourceFile);
JsonParser baseParser = mapper.getFactory().createParser(inputSource);
JsonParser filteredParser = new FilteringParserDelegate(baseParser,
new JsonPointerBasedFilter(basePath), false, false);) {
// Call nextToken once to initialize the filteredParser
JsonToken basePathToken = filteredParser.nextToken();
if (basePathToken != JsonToken.START_ARRAY) {
throw new IllegalStateException("Base path did not point to an array: found "
+ basePathToken);
}
while (filteredParser.nextToken() == JsonToken.START_OBJECT) {
// Parse each object inside of the array into a separate tree model
// to keep a fixed memory footprint when parsing files
// larger than the available memory
JsonNode nextNode = mapper.readTree(filteredParser);
// Consume/process the node for example:
JsonPointer fieldRelativePath = JsonPointer.compile("/test1");
JsonNode valueNode = nextNode.at(fieldRelativePath);
if (!valueNode.isValueNode()) {
throw new IllegalStateException("Did not find value at "
+ fieldRelativePath.toString()
+ " after setting base to " + basePath.toString());
}
System.out.println(valueNode.asText());
}
}
I am trying to dynamicalyl populate my jqGrid...
I have been running into a hell of a time getting my jquery grid to populate with data. How would you set up your jquery string? I create an object like so...
public static object JsonHelper(TemplateModel model){
var values = model.Template;
var JsonDataList = new {
total = 1,
page = 1,
records = model.Template.Count,
rows = (from val in values
select new {
cell = //new string(
":[\"id\" :\"" + val.EncounterId +",\""+
"\""+val.MRN + ",\""+
"\""+val.HostpitalFinNumber +",\""+
"\""+val.FirstName+",\"" +
"\""+val.LastName +",\"" +
"\""+val.DateOfBirth.ToString() +",\""+
"\""+val.CompletedPathway +",\""+
"\""+val.CompletedPathwayReason +",\""+
"\""+val.PCPAppointmentDateTime.ToString() + ",\""+
"\""+ val.SpecialistAppointmentDateTime.ToString() + ",\""+
"\""+val.AdminDate.ToString()+"\"]"
}).ToString()//.ToArray()
};
return JsonDataList;
}
That is just an object,
However I return the object using the Json methbod call...
Here is what I do...
return Json(DataRepository.JsonHelper(model.FirstOrDefault()), JsonRequestBehavior.AllowGet);
I get the model from the search call... I have know idea what I am doing wrong... Can somebody give me a simple example of how to turn a simple object into json?
I suggest you look into Google's gson library. I used it when working with JSON and it worked perfectly.
Well, I just used a string builder and a good JSON debugger to get the right strings, and it appears as though it works...