Как построить график Синоби на основе данных JSON без ключа, используя цель с

У меня возникла проблема с отображением данных JSON в этой структуре ниже.

{"response":{"hash":"0fea72f2bea9820c18227a655b42fe66","resp_code":"GRAPH_RETRIEVED","code":200},"resultstats":{"record_count":46},"ana_uoms":["°C"],"data":[{"asset_id":204,"company_id":30,"asset_name":"WIF","stats":{"min":1.4,"max":6.9,"min_tstamps_count":1,"min_tstamps":["2015-03-17 08:30:00"],"max_tstamps":["2015-03-17 11:00:00","2015-03-17 11:30:00","2015-03-17 13:40:00","2015-03-17 14:50:00"],"mkt":5.91,"max_tstamps_count":4,"avg":5.8},"component_type":"ana_in","component_description":"WFt","site_name":"Kll","alarms":[],"sampling_rate":10,"region_name":"ll","component_id":8340,"company_name":"lb","uom":"°C","uom_decimal_places":1,"unit_sn":"3310","resolves":[],"records":[["2015-03-17 08:00",2.6],["2015-03-17 08:10",3.9],["2015-03-17 08:20",2.4],["2015-03-17 08:30",1.4],["2015-03-17 08:40",3.1],["2015-03-17 08:50",4.4],["2015-03-17 09:00",5.1],["2015-03-17 09:10",5.5],["2015-03-17 09:20",6.1],["2015-03-17 09:30",6.2],["2015-03-17 09:40",5.3],["2015-03-17 09:50",6.4],["2015-03-17 10:00",6.6],["2015-03-17 10:10",6.7],["2015-03-17 10:20",6.8],["2015-03-17 10:30",5.2],["2015-03-17 10:40",6.3],["2015-03-17 10:50",6.7],["2015-03-17 11:00",6.9],["2015-03-17 11:10",6],["2015-03-17 11:20",6.6],["2015-03-17 11:30",6.9],["2015-03-17 11:40",5.9],["2015-03-17 11:50",6.6],["2015-03-17 12:00",6.8],["2015-03-17 12:10",6.1],["2015-03-17 12:20",6.6],["2015-03-17 12:30",5.6],["2015-03-17 12:40",6.2],["2015-03-17 12:50",6.8],["2015-03-17 13:00",5.7],["2015-03-17 13:10",6.6],["2015-03-17 13:20",5.8],["2015-03-17 13:30",6.4],["2015-03-17 13:40",6.9],["2015-03-17 13:50",6],["2015-03-17 14:00",6.7],["2015-03-17 14:10",5.2],["2015-03-17 14:20",6.5],["2015-03-17 14:30",5.8],["2015-03-17 14:40",6.3],["2015-03-17 14:50",6.9],["2015-03-17 15:00",6.6],["2015-03-17 15:10",5.9],["2015-03-17 15:20",6.3],["2015-03-17 15:30",6.5]]},{"asset_id":204,"company_id":30,"asset_name":"Wft","stats":{"min":2.9,"max":6.8,"min_tstamps_count":1,"min_tstamps":["2015-03-17 08:30:00"],"max_tstamps":["2015-03-17 11:00:00","2015-03-17 11:30:00","2015-03-17 12:00:00","2015-03-17 13:40:00"],"mkt":5.8,"max_tstamps_count":4,"avg":5.7},"component_type":"ana_in","component_description":"WIF Right Back","site_name":"Ktore","alarms":[],"sampling_rate":10,"region_name":"Kano","component_id":8341,"company_name":"lls","uom":"°C","uom_decimal_places":1,"unit_sn":"3310","resolves":[],"records":[["2015-03-17 08:00",3.2],["2015-03-17 08:10",4.2],["2015-03-17 08:20",3.1],["2015-03-17 08:30",2.9],["2015-03-17 08:40",3.7],["2015-03-17 08:50",4.5],["2015-03-17 09:00",5.2],["2015-03-17 09:10",5.6],["2015-03-17 09:20",6.1],["2015-03-17 09:30",6.3],["2015-03-17 09:40",4.8],["2015-03-17 09:50",6.3],["2015-03-17 10:00",6.5],["2015-03-17 10:10",6.6],["2015-03-17 10:20",6.7],["2015-03-17 10:30",4.5],["2015-03-17 10:40",6.3],["2015-03-17 10:50",6.6],["2015-03-17 11:00",6.8],["2015-03-17 11:10",5.9],["2015-03-17 11:20",6.5],["2015-03-17 11:30",6.8],["2015-03-17 11:40",5.7],["2015-03-17 11:50",6.5],["2015-03-17 12:00",6.8],["2015-03-17 12:10",5.9],["2015-03-17 12:20",6.6],["2015-03-17 12:30",5],["2015-03-17 12:40",6.2],["2015-03-17 12:50",6.7],["2015-03-17 13:00",5.5],["2015-03-17 13:10",6.5],["2015-03-17 13:20",5.2],["2015-03-17 13:30",6.2],["2015-03-17 13:40",6.8],["2015-03-17 13:50",5.8],["2015-03-17 14:00",6.6],["2015-03-17 14:10",4.5],["2015-03-17 14:20",6.4],["2015-03-17 14:30",5.2],["2015-03-17 14:40",6.2],["2015-03-17 14:50",6.7],["2015-03-17 15:00",6.4],["2015-03-17 15:10",5.2],["2015-03-17 15:20",6.2],["2015-03-17 15:30",6.1]]}],"ana_thresholds":[["<1.0"],[">8.0"]],"parameters":{"end_date":"2015-03-17 15:30","start_date":"2015-03-17 08:00","sampling_rate":10}}

Я в основном пытаюсь использовать пробную библиотеку графов Шиноби для построения этих данных json, но совершенно не понимаю, как анализировать объекты выше. В JSON у меня есть значения даты и времени и температуры. Мне удается увидеть ответ синтаксического анализа в моей консоли. Однако на графике нет данных объекта для построения, потому что я не передаю никакие значения json в ряд, так как я не знаю, как это делается. Пожалуйста, помогите, потому что я не видел подобного вопроса в stackru.

Вот мой фрагмент кода.

- (void) loadData{
// Parse units offline from the webservice.
@try{

    NSString *delete = [[NSString alloc] initWithFormat:@""];
    NSString *logOut = [NSString stringWithFormat:@"MY URL"];

    NSURL *url=[NSURL URLWithString:logOut];
    NSLog(@"Asset list: %@", url);
    NSData *postData =[delete dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    NSString *postLength = [ NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:url];
    [request setHTTPMethod:@"GET"];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request setHTTPBody:postData];

    //[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];

    NSError *error = [[NSError alloc] init];
    NSHTTPURLResponse *response = nil;
    NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];

    NSLog(@"Reponse code: %ld", (long)[response statusCode]);
    if ([response statusCode] >= 200 && [response statusCode] < 300)
    {
        NSLog(@"Response ==> %@", responseData);
        @try{
            NSError *error = nil;
       // NSMutableArray* jsonDetails = [[NSMutableArray alloc]init];
            NSDictionary *jsonDetails = [NSJSONSerialization JSONObjectWithData:urlData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error];
            NSArray *graphData = [ jsonDetails objectForKey:@"records"];
             NSLog(@"Retrieving graph: %@", jsonDetails);

            for (NSDictionary* jsonPoint  in graphData) {
                SChartDataPoint* datapoint = [self dataPointForDate:jsonPoint[@"date"]
                                                           andValue:jsonPoint[@"temp"]];
                NSLog(@"SChart point: %@", datapoint);
                [_timeSeries addObject:datapoint];
            }
        }
        @catch (NSException *e){
            NSLog(@"Try catch block: %@", e);
        }
        @finally{
            // [self.tblRegion reloadData];
            NSLog(@"finally");
        }


    }

}
@catch (NSException * e) {
    NSLog(@"Exception: %@", e);

}

}

3 ответа

Решение

Благодаря помощи Саммида, считаю, что это близкий ответ на мой вопрос. Фрагмент ниже почти идеален. Единственное, что мне все еще нужно изменить формат даты, чтобы получить точки данных в серии.

{
        NSLog(@"Response ==> %@", responseData);

            NSError *error = nil;
            jsonDetails = [NSJSONSerialization JSONObjectWithData:urlData options:kNilOptions error:&error];
        NSArray *keys = [jsonDetails allKeys];
        // values in foreach loop
        for (NSString *key in keys) {
            // NSLog(@"%@ is %@",key, [jsonDetails objectForKey:key]);

            data = [jsonDetails objectForKey:@"data"];
            graphData = [data[0]objectForKey:@"records"];
            datapoint = [[SChartDataPoint alloc] init];
            // NSLog(@"Record for the graph: %@", graphData);
            // results = [jsonDetails objectForKey:@"resultstats"];
            // recordCount = [results objectForKey:@"record_count"];

        for (int i=0; i< [graphData count]; i++){
            NSArray *record = graphData[i];
            // NSLog(@"Record value: %@", record);
            datapoint.xValue = record[0]; // date
            NSLog(@"Date/time: %@", datapoint.xValue);
            datapoint.yValue = record[1]; // number
            NSLog(@"Temp: %@", datapoint.yValue);
            datapoint = [self dataPointForDate:datapoint.xValue
                                                       andValue:datapoint.yValue];

            NSLog(@"Adding datapoint to series: %@", datapoint);
            [_timeSeries addObject:datapoint];
        }

        }

    }

Вот консоль, поставленная. Я не буду вставлять весь вывод консоли, потому что ответ json и NSLog я положил для отладки. По какой-то причине вы можете видеть, когда я добавляю объекты datapoint в серию. Значение datapoint.xValue равно нулю, поэтому я все еще не вижу график в приложении. Я изменил формат даты на гггг-ММ-дд ЧЧ: мм, и вот мой вывод на консоль. Все еще никакой график не построен.

TimeSeriesChart[952:468171] Adding datapoint to series: { index=0, x=2015-03-22 13:20:00 +0000, y=6.4, selected=N }
2015-03-23 07:49:01.682 TimeSeriesChart[952:468171] Date/time: 2015-03-22 15:30
2015-03-23 07:49:01.683 TimeSeriesChart[952:468171] Temp: 6.3
2015-03-23 07:49:01.685 TimeSeriesChart[952:468171] Time/Date format: 2015-03-22 13:30:00 +0000
2015-03-23 07:49:01.685 TimeSeriesChart[952:468171] Adding datapoint to series: { index=0, x=2015-03-22 13:30:00 +0000, y=6.3, selected=N }
2015-03-23 07:49:01.697 TimeSeriesChart[952:468171] ShinobiCharts: Attempting to update axis data range with nil series min or max. Axis range not updated.
From: SChartDateTimeAxis at 0x15d64d10, axisRange = { 0.000000, 1.000000 }, defaultRange = { 1970-01-01 00:00:00 +0000, 1970-01-01 00:00:01 +0000 }, maxRange = { 1970-01-01 00:00:00 +0000, 1970-01-01 00:00:01 +0000 }
2015-03-23 07:49:01.698 TimeSeriesChart[952:468171] ShinobiCharts: Attempting to update axis data range with nil series min or max. Axis range not updated.
From: SChartNumberAxis at 0x19c852e0, axisRange = { 0.000000, 1.000000 }, defaultRange = { 0.000000, 1.000000 }, maxRange = { 0.000000, 1.000000 }

Я исправил вышеуказанную ошибку, следуя предложенному Саммиду ответу;

    for (NSArray *record in graphData) {

            // NSArray *record = graphData[i];
            // NSLog(@"Record value: %@", record);
            NSString *dateString = [NSString stringWithFormat:@"%@",[record objectAtIndex:0]];
            NSDate *date = [self dateFromString:dateString];
            datapoint.xValue = date; // date
            NSLog(@"Date/time: %@", datapoint.xValue);
            // NSString *date = datapoint.xValue;
            datapoint.yValue = record[1]; // number
            NSLog(@"Temp: %@", datapoint.yValue);
            datapoint = [self dataPointForDate:record[0]
                                            andValue:record[1]];

            NSLog(@"Adding datapoint to series: %@", datapoint);
            [_timeSeries addObject:datapoint];
        }

Теперь я счастлив и продолжаю следовать учебному пособию Сэммейда по внедрению блога rand SammyD. Смотрите скриншоты вывода. Спасибо всем вам, ребята.

На портрете график выглядит не очень красиво, любые предложения приветствуются. Напомним, что данные, представленные здесь, содержат более 4000 данных. Я думаю, что их можно лучше масштабировать, пожалуйста, поделитесь тем, что я могу сделать, чтобы сделать график более представительным, как iOS-приложение.

Из вашей структуры JSON я думаю, что ваша диаграмма должна иметь 2 серии. Один для данных [0] и один для данных [1]. Если я не прав, вы можете отредактировать мой ответ, чтобы удовлетворить ваши потребности.

Прежде всего, вы можете создать 2 полезных класса. Первый - "ChartPoint":

@interface ChartPoint : NSObject

@property(strong,nonatomic) NSDate *date;
@property(strong,nonatomic) NSNumber *value;

@end

Второй "ChartData":

@interface ChartData : NSObject

@property (strong,nonatomic) NSString *siteName;
@property (strong,nonatomic) NSMutableArray *chartPoints;

@end

который будет содержать информацию о вашей серии. Название вашей серии и количество ChartPoints.

Следующим шагом является настройка графика. Вы можете увидеть, как это делается на примерах ShinobiChart. Вот код для этого:

-(void)setUpChart
{
    schart = [[ShinobiChart alloc] initWithFrame:self.chartView.bounds];
    schart.delegate=self;
    schart.datasource = self;
    schart.autoresizingMask =  ~UIViewAutoresizingNone;
    schart.licenseKey = @"your licence";

    schart.legend.hidden=NO;

    //X AXIS CONFIGURATION
    SChartDateTimeAxis *xAxis = [[SChartDateTimeAxis alloc] init];
    xAxis.style.interSeriesPadding = @0;

    xAxis.style.majorTickStyle.showLabels = YES;
    xAxis.style.majorTickStyle.showTicks  = YES;

    schart.xAxis = xAxis;

    //Y AXIS CONFIGURATION
    SChartAxis *yAxis = [[SChartNumberAxis alloc] init];

    yAxis.style.majorGridLineStyle.showMajorGridLines=YES;

    yAxis.style.majorTickStyle.showLabels = YES;
    yAxis.style.majorTickStyle.showTicks  = YES;

    schart.yAxis = yAxis;

    // add to the view
    [self.chartView addSubview:schart];
}

После этого вам нужно проанализировать ответ вашего сервера и создать экземпляры вышеуказанных полезных классов. Если вы вычерчиваете количество рядов, ваш контроллер представления должен содержать массив "chartSeries" с объектами "ChartData". После десериализации ответа на NSDictionary вы должны сделать следующее:

-(void)parseResponse:(NSDictionary*)response
{
    chartSeries = [[NSMutableArray alloc] init];

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];

    NSArray *data = [response objectForKey:@"data"];

    for (NSDictionary *d in data)
    {
        NSString *sitename = [d objectForKey:@"site_name"];
        NSArray *records = [d objectForKey:@"records"];

        ChartData *cd = [[ChartData alloc] init];
        cd.siteName=sitename;
        cd.chartPoints = [[NSMutableArray alloc] init];

        for (NSArray *r in records)
        {
            NSString *dateString = [NSString stringWithFormat:@"%@",[r objectAtIndex:0]];
            NSDate *date = [formatter dateFromString:dateString];


            NSNumber *value = [r objectAtIndex:1];

            ChartPoint *point =[[ChartPoint alloc] init];
            point.date=date;
            point.value = value;

            [cd.chartPoints addObject:point];
        }


        [chartSeries addObject:cd];
    }

    [schart reloadData];
    [schart redrawChart];
}

Вы видите, что после завершения анализа вы должны перезагрузить данные диаграммы и перерисовать их. Это из-за протокола SChartDatasource, как и UITableViews.

- (NSInteger)numberOfSeriesInSChart:(ShinobiChart *)chart
{
    return chartSeries.count;
}

- (NSInteger)sChart:(ShinobiChart *)chart numberOfDataPointsForSeriesAtIndex:(NSInteger)seriesIndex
{
    ChartData * data  = [chartSeries objectAtIndex:seriesIndex];
    return data.chartPoints.count;
}

-(SChartSeries *)sChart:(ShinobiChart *)chart seriesAtIndex:(NSInteger)index
{
    ChartData * data  = [chartSeries objectAtIndex:index];

    SChartColumnSeries *columnSeries = [[SChartColumnSeries alloc] init];
    columnSeries.title=data.siteName;

    return columnSeries;
}

- (id<SChartData>)sChart:(ShinobiChart *)chart dataPointAtIndex:(NSInteger)dataIndex forSeriesAtIndex:(NSInteger)seriesIndex
{
    ChartData * data  = [chartSeries objectAtIndex:seriesIndex];
    ChartPoint *point = [data.chartPoints objectAtIndex:dataIndex];

    SChartDataPoint *dp = [[SChartDataPoint alloc] init];

    dp.yValue = point.value;
    dp.xValue =point.date;

    return dp;
}

Я надеюсь, что это поможет вам!

Синобихарт использует ту же модель, что и UITableView для предоставления данных - в том, что он использует объект источника данных. Вам нужен объект, который соответствует SChartDatasource протокол - который имеет 4 обязательных метода для предоставления данных на диаграмму. К ним относится предоставление количества точек данных и самих точек данных (среди прочих).

Если вы сохраняете точки данных, которые вы создаете, в массив, то вы можете затем передать их на диаграмму в соответствующем SChartDatasource методы.

Вместо того, чтобы повторять это здесь, я отсылаю вас к краткому руководству по shinobicharts, в котором рассказывается об основах предоставления данных в диаграмму:

http://www.shinobicontrols.com/docs/ShinobiControls/ShinobiCharts/2.7.0/Premium/Normal/user_guide.html

У структуры JSON, которая у вас есть, есть поле записей со следующей структурой:

"records":[["2015-03-17 08:00",2.6],["2015-03-17 08:10",3.9],...

Это массив массивов, т. Е. Каждая точка данных представлена ​​массивом, где первый элемент является датой, а второй элемент - значением.

Вам необходимо обновить следующее:

for (NSDictionary* jsonPoint  in graphData) {
    SChartDataPoint* datapoint = [self dataPointForDate:jsonPoint[@"date"]
                                               andValue:jsonPoint[@"temp"]];
    NSLog(@"SChart point: %@", datapoint);
    [_timeSeries addObject:datapoint];
}

Вместо NSDictionary объекты, у вас действительно есть NSArray:

for (NSArray* jsonPoint  in graphData) {
    SChartDataPoint* datapoint = [self dataPointForDate:jsonPoint[0]
                                               andValue:jsonPoint[1]];
    NSLog(@"SChart point: %@", datapoint);
    [_timeSeries addObject:datapoint];
}

Обратите внимание, что вам может понадобиться проанализировать значение даты из NSString для NSDate - в зависимости от того, что ваш dataPointForDate:andValue: метод делает. Вы можете сделать это с NSDateFormatter,

Другие вопросы по тегам