4

I'm trying to extend the HelpScoutNet project so I can take advantage of reports. I'm having one hell of a time getting the JSON I get from HelpScout to deserialize into my classes. Hopefully you guys can tell me what I'm doing wrong.

JSON according to the API documents:

 {
  "filterTags": [
    {
      "id": 123,
      "name": "sample-tag"
    },
    ...
  ],
  "user": {
    "id": 4,
    "hasPhoto": true,
    "createdAt": "2010-09-03T15:55:48Z",
    "name": "John Smith",
    "totalCustomersHelped": 6580,
    "photoUrl": "http://example.com/pic.jpg"
  },
  "current": {
    "startDate": "2015-01-01T00:00:00Z",
    "endDate": "2015-01-31T23:59:59Z",
    "totalDays": 30,
    "resolved": 1,
    "conversationsCreated": 15,
    "closed": 3,
    "totalReplies": 58,
    "resolvedOnFirstReply": 0,
    "percentResolvedOnFirstReply": 0.0,
    "repliesToResolve": 2.0,
    "handleTime": 78.96,
    "happinessScore": 66.66666666666666,
    "responseTime": 2278004,
    "resolutionTime": 2278004.0,
    "repliesPerDay": 1.9333333333333333,
    "customersHelped": 26,
    "totalConversations": 19,
    "conversationsPerDay": 0.6333333333333333,
    "busiestDay": 5
  },
  "previous": {
    "startDate": "2014-01-01T00:00:00Z",
    "endDate": "2014-01-31T23:59:59Z",
    "totalDays": 30,
    "resolved": 12,
    "conversationsCreated": 2,
    "closed": 33,
    "totalReplies": 40,
    "resolvedOnFirstReply": 4,
    "percentResolvedOnFirstReply": 0.3333333333333333,
    "repliesToResolve": 2.1666666666666665,
    "handleTime": 0.0,
    "happinessScore": 23.529411764705884,
    "responseTime": 2357169,
    "resolutionTime": 4318101.5,
    "repliesPerDay": 1.3333333333333333,
    "customersHelped": 16,
    "totalConversations": 42,
    "conversationsPerDay": 0.4
  },
  "deltas": {
    "totalConversations": -54.761904761904766,
    "customersHelped": 62.5,
    "happinessScore": 43.13725490196077,
    "repliesPerDay": 45.000000000000014,
    "resolvedOnFirstReply": -100.0,
    "handleTime": 0.0,
    "conversationsPerDay": 58.33333333333333,
    "resolved": -91.66666666666666,
    "repliesToResolve": -7.692307692307687,
    "activeConversations": -54.761904761904766,
    "totalReplies": 44.99999999999999,
    "closed": -90.9090909090909,
    "responseTime": -3.3584779029420475,
    "resolutionTime": -47.245241919394445,
    "conversationsCreated": 650.0
  }
}

JSON I get back from API:

"{\"filterTags\":[{\"name\":\"general questions\",\"id\":295508},{\"name\":\"request/suggestion\",\"id\":372291},{\"name\":\"support.dd.com incorrect\",\"id\":547376},{\"name\":\"status update\",\"id\":295502},{\"name\":\"support.dd.com other\",\"id\":547378},{\"name\":\"promos/gift cards\",\"id\":295547}],\"user\":{\"createdAt\":\"2015-05-04T16:32:21Z\",\"photoUrl\":\"https://d33v4339jhl8k0.cloudfront.net/users/99999.23342.jpg\",\"hasPhoto\":true,\"name\":\"John Doe\",\"totalCustomersHelped\":261,\"id\":99999},\"current\":{\"startDate\":\"2015-08-15T12:00:00Z\",\"endDate\":\"2015-08-16T18:00:00Z\",\"totalDays\":1,\"resolved\":4,\"conversationsCreated\":0,\"closed\":11,\"totalReplies\":5,\"resolvedOnFirstReply\":3,\"percentResolvedOnFirstReply\":60.0,\"repliesToResolve\":1.25,\"handleTime\":346.6,\"happinessScore\":0.0,\"responseTime\":3467,\"resolutionTime\":4704.25,\"repliesPerDay\":5.0,\"customersHelped\":4,\"totalConversations\":12,\"conversationsPerDay\":12.0,\"busiestDay\":6}}"

My Classes:

public class User
{
    [DefaultValue(0)]
    public int ID { get; set; }
    public bool HasPhoto { get; set; }
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public DateTime? CreatedAt { get; set; }
    public string Name { get; set; }
    public int TotalCustomersHelped { get; set; }
    public string PhotoURL { get; set; }
}

public class TimeRangeStats
{
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public DateTime? StartDate { get; set; }
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public DateTime? EndDate { get; set; }
    public int TotalDays { get; set; }
    public int Resolved { get; set; }
    public int ConversationsCreated { get; set; }
    public int Closed { get; set; }
    public int TotalReplies { get; set; }
    public int ResolvedOnFirstReply { get; set; }
    public double PercentResolvedOnFirstReply { get; set; }
    public double RepliesToResolve { get; set; }
    public double HandleTime { get; set; }
    public double HappinessScore { get; set; }
    public double ResponseTime { get; set; }
    public double ResolutionTime { get; set; }
    public double RepliesPerDay { get; set; }
    public int CustomersHelped { get; set; }
    public int TotalConversations { get; set; }
    public double ConversationsPerDay { get; set; }
    public int BusiestDay { get; set; }
}

public class MultipleTimeRangeStats
{
    public double TotalConversations { get; set; }
    public double CustomersHelped { get; set; }
    public double HappinessScore { get; set; }
    public double RepliesPerDay { get; set; }
    public double ResolvedOnFirstReply { get; set; }
    public double HandleTime { get; set; }
    public double ConversationsPerDay { get; set; }
    public double Resolved { get; set; }
    public double RepliesToResolve { get; set; }
    public double ActiveConversations { get; set; }
    public double TotalReplies { get; set; }
    public double Closed { get; set; }
    public double ResponseTime { get; set; }
    public double ResolutionTime { get; set; }
    public double ConversationsCreated { get; set; }
}

public class Tag
{
    public string Name { get; set; }
    [DefaultValue(0)]
    public long ID { get; set; }
}

public class UserReport
{
    public List<Tag> FilterTags { get; set; }
    public User User { get; set; }
    public TimeRangeStats Current { get; set; }
    public TimeRangeStats Previous { get; set; }
    public MultipleTimeRangeStats Deltas { get; set; }
}

Serializer Settings:

private JsonSerializerSettings _serializerSettings
        {
            get
            {
                var serializer = new JsonSerializerSettings
                {
                    ContractResolver = new CamelCasePropertyNamesContractResolver(),
                    NullValueHandling = NullValueHandling.Ignore,
                    DefaultValueHandling = DefaultValueHandling.Ignore,
                    DateFormatHandling = DateFormatHandling.IsoDateFormat,                    
                };
                serializer.Converters.Add(new StringEnumConverter {CamelCaseText = true});

                return serializer;
            }
        }

I hope this is not an overwhelming amount of information to ask about.

HelpScoutNet: https://github.com/Selz/HelpScoutNet

Relevant HelpScout API: http://developer.helpscout.net/help-desk-api/reports/user/user/

Edit: Got the tracer to work, get this result. Which is thoroughly confusing that it can't find those properties yet it works on other classes that as far as I can tell are built the same:

2015-08-18T00:59:30.188 Info Started deserializing HelpScoutNet.SingleItem`1[Hel
pScoutNet.Model.Report.User.UserReports.UserReport]. Path 'filterTags', line 1,
position 14.
2015-08-18T00:59:30.189 Verbose Could not find member 'filterTags' on HelpScoutN
et.SingleItem`1[HelpScoutNet.Model.Report.User.UserReports.UserReport]. Path 'fi
lterTags', line 1, position 14.
2015-08-18T00:59:30.194 Verbose Could not find member 'user' on HelpScoutNet.Sin
gleItem`1[HelpScoutNet.Model.Report.User.UserReports.UserReport]. Path 'user', l
ine 1, position 276.
2015-08-18T00:59:30.198 Verbose Could not find member 'current' on HelpScoutNet.
SingleItem`1[HelpScoutNet.Model.Report.User.UserReports.UserReport]. Path 'curre
nt', line 1, position 470.
2015-08-18T00:59:30.200 Info Finished deserializing HelpScoutNet.SingleItem`1[He
lpScoutNet.Model.Report.User.UserReports.UserReport]. Path '', line 1, position
896.
2
  • 1
    The JSON in your question corresponds to a UserReport not a SingleItem<UserReport> -- there's no outer {"item": ...} container object. How are you trying to deserialize it? Commented Aug 18, 2015 at 8:23
  • Oh wow. I must be completely blind to have missed that. Please post this as an answer, I will happily mark it as correct, that was the issue. Totally flying by the seat of my pants on this one. Commented Aug 18, 2015 at 8:28

1 Answer 1

3

The JSON in your question corresponds to your UserReport class, not a SingleItem<UserReport> -- there's no outer {"item": ...} container object. So you need to deserialize it as such.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.