function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Kenji775Kenji775 

Weird JSON Deserialize error

Hey all.

I'm working on a custom APEX REST service that will take a JSON payload delivered in the request body and deserialize it to a custom class type. This works just fine in my unit test, and when running from the developer console, but actually attempting the same type of request with the apigee app console results in the fairly cryptic error

 

"message": "Can not deserialize SObject out of VALUE_NUMBER_FLOAT token at [line:1, column:1]", "errorCode": "JSON_PARSER_ERROR"

 

Also, I have seen the error

 

"No such column 'reviewers' on sobject of type Challenge__c" show up. 

 

The payload contains a single challenge__c object, an 4 lists of other object types. I am trying to deserialize the into this wrapper class so then I can insert the challenge, and then the lists of all the records related to it.

 

The line causing this error is 

challengeService.challengePayload challengeData = (challengeService.challengePayload)JSON.deserialize(jsonBody, challengeService.challengePayload.class);

 The defenition of the class is

    global class challengePayload
    {
        public Challenge__c challenge;
        public list<Challenge_Comment_Notifier__c> notifiers = new list<Challenge_Comment_Notifier__c>();
        public list<Challenge_Category__c> categories = new list<Challenge_Category__c>();
        public list<Challenge_Prize__c> prizes = new list<Challenge_Prize__c>();
        public list<Challenge_Reviewer__c> reviewers = new list<Challenge_Reviewer__c>();    
    }  

 

 

Running this code works just fine, both in my unit test, and from the console.

        string jsonBody = '{"reviewers":[{"attributes":{"type":"Challenge_Reviewer__c"},"Member_Reference__c":"testguy1"}],"prizes":[{"attributes":{"type":"Challenge_Prize__c"},"Place__c":1,"Points__c":1000,"Prize__c":"$1000.00","Value__c":1000.00},{"attributes":{"type":"Challenge_Prize__c"},"Place__c":2,"Points__c":500,"Prize__c":"$500.00","Value__c":500.00},{"attributes":{"type":"Challenge_Prize__c"},"Place__c":3,"Points__c":200,"Prize__c":"$200.00","Value__c":200.00}],"notifiers":[{"attributes":{"type":"Challenge_Comment_Notifier__c"},"Member_Reference__c":"testguy1"}],"challenge":{"attributes":{"type":"Challenge__c"},"Name":"test Challenge","End_Date__c":"2012-03-27T17:15:15.261+0000","Challenge_Id__c":"1231231232","Winner_Announced__c":"2012-04-03","Start_Date__c":"2012-03-20T17:15:15.262+0000","Description__c":"test Challenge","Requirements__c":"Test","Status__c":"hidden"},"categories":[{"attributes":{"type":"Challenge_Category__c"},"Category__c":"a04E00000017pWrIAI"}]}';      
        challengeService.challengePayload challengeData = (challengeService.challengePayload)JSON.deserialize(jsonBody, challengeService.challengePayload.class);

 

But running this

https://snap.apigee.com/GBvRyx

 

Not really sure what's going on, and why the erros seem to be flip flopping. I am wondering if perhaps apigee is not encoding the request properly or something? Below is my full class. 

 

/************************************
Name: challengeService
Author: Daniel Llewellyn (Kenji776)
Date: 3/20/2012
Description: Creates a cloudspokes challenge and it's associated records when valid
             json data is passed to the post request. Data must include keys for challenge,
             and optionally may includes prizes, reviewers, categories, and people to notify on comment.
*************************************/
@RestResource(urlMapping='/challengeService/v1/*') 
global class challengeService
{
    @HttpPost
    global static string doPost(RestRequest req, RestResponse res) 
    {
        string returnMessage = 'Operation pending';
        try
        {
            //now we need to get at the body of the request, since that is going to contain all juicy data needed for creating the related records.
            string jsonBody = req.requestBody.toString();
            
            //serialize the request body into a challenge data payload, which has the data for the challenge and all it's associated records.
            challengePayload challengeData = (challengePayload)JSON.deserialize(jsonBody, challengePayload.class);
            
            //insert the challenge itself.
            insert challengeData.challenge;
                     
            //populate the notifiers with the challenge Id
            for(Challenge_Comment_Notifier__c ccn : challengeData.notifiers)
            {
                ccn.challenge__c = challengeData.challenge.id;
            }
            
            //insert the notifiers
            database.insert(challengeData.notifiers);
            
            //populate the categories with the challenge Id
            for(Challenge_Category__c cc : challengeData.categories)
            {
                cc.challenge__c = challengeData.challenge.id;
            }
            
            //insert the categories
            database.insert(challengeData.categories);        
    
            //populate the prizes with the challenge Id
            for(Challenge_prize__c p : challengeData.prizes)
            {
                p.challenge__c = challengeData.challenge.id;
            }
            
            //insert the categories
            database.insert(challengeData.prizes); 
    
            //populate the prizes with the challenge Id
            for(challenge_Reviewer__c r : challengeData.reviewers)
            {
                r.challenge__c = challengeData.challenge.id;
            }
            
            //insert the categories
            database.insert(challengeData.reviewers);        
            
            returnMessage = challengeData.challenge.id;
        }
        catch(exception ex)
        {
            returnMessage = ex.getMessage() + ' Cause is ' + ex.getCause() + ' on line ' + ex.getLineNumber();
        }
        return returnMessage;
    }  

    global static list<sObject> populatLookup(list<sObject> objectsList)
    {
        map<string,id> lookupStringToMemberIdMap = new map<string,id>();
        
        for(sObject obj : objectsList)
        {
            if(obj.get('Member_Reference__c') != null)
            {
                lookupStringToMemberIdMap.put((string) obj.get('Member_Reference__c'), null);         
            }
        }    
        list<Member__c> members = [select id, email__c, name from Member__c where name in : lookupStringToMemberIdMap.keySet() or email__c in : lookupStringToMemberIdMap.keySet()];  
        
        for(Member__c member : members)
        {
            lookupStringToMemberIdMap.put(member.email__c,member.id);
            lookupStringToMemberIdMap.put(member.name,member.id);
        }
        
        for(sObject obj : objectsList)
        {
            if(obj.get('Member_Reference__c') != null)
            {    
                obj.put('member__c',lookupStringToMemberIdMap.get((string) obj.get('Member_Reference__c')));
                obj.put('Member_Reference__c',null);
            }
        }    
        
        return objectsList;
    }
    
    //custom class to handle the challenge and all it's associated data.
    global class challengePayload
    {
        public Challenge__c challenge;
        public list<Challenge_Comment_Notifier__c> notifiers = new list<Challenge_Comment_Notifier__c>();
        public list<Challenge_Category__c> categories = new list<Challenge_Category__c>();
        public list<Challenge_Prize__c> prizes = new list<Challenge_Prize__c>();
        public list<Challenge_Reviewer__c> reviewers = new list<Challenge_Reviewer__c>();    
    }  

    @isTest
    public static void testCreateChallenge()
    {
        //create the parent objects so our junction objects have something to reference later.
        Category__c cat1 = new Category__c();
        cat1.name = 'test category 1';
        insert cat1;
        
        Member__c member1 = new Member__c();
        member1.name = 'testguy1';
        member1.email__c = 'testguy1@testguyland.com';
        member1.Profile_Pic__c = 'mypics.jpg';
        
        insert member1;

        //validate json string deserialization into custom class

        string jsonBody = '{"reviewers":[{"attributes":{"type":"Challenge_Reviewer__c"},"Member_Reference__c":"testguy1"}],"prizes":[{"attributes":{"type":"Challenge_Prize__c"},"Place__c":1,"Points__c":1000,"Prize__c":"$1000.00","Value__c":1000.00},{"attributes":{"type":"Challenge_Prize__c"},"Place__c":2,"Points__c":500,"Prize__c":"$500.00","Value__c":500.00},{"attributes":{"type":"Challenge_Prize__c"},"Place__c":3,"Points__c":200,"Prize__c":"$200.00","Value__c":200.00}],"notifiers":[{"attributes":{"type":"Challenge_Comment_Notifier__c"},"Member_Reference__c":"testguy1"}],"challenge":{"attributes":{"type":"Challenge__c"},"Name":"test Challenge","End_Date__c":"2012-03-27T17:15:15.261+0000","Challenge_Id__c":"1231231232","Winner_Announced__c":"2012-04-03","Start_Date__c":"2012-03-20T17:15:15.262+0000","Description__c":"test Challenge","Requirements__c":"Test","Status__c":"hidden"},"categories":[{"attributes":{"type":"Challenge_Category__c"},"Category__c":"a04E00000017pWrIAI"}]}';      
        challengeService.challengePayload challengeData = (challengeService.challengePayload)JSON.deserialize(jsonBody, challengeService.challengePayload.class);
                
        //Create the challenge payload object. We will serialize it later and send it to the post method.
        challengePayload myPayload = new challengePayload();
        myPayload.challenge = new challenge__c();
        myPayload.challenge.Challenge_Id__c = '001231231232';
        myPayload.challenge.Name = 'test Challenge';
        myPayload.challenge.Description__c = 'test Challenge';
        myPayload.challenge.End_Date__c = dateTime.now().addDays(7);
        myPayload.challenge.Requirements__c = 'Test';
        myPayload.challenge.Start_Date__c = dateTime.now();
        myPayload.challenge.Status__c = 'hidden';
        myPayload.challenge.Winner_Announced__c = date.today().addDays(14);
        
        
        Challenge_Comment_Notifier__c notifier1 = new Challenge_Comment_Notifier__c();
        notifier1.Member_Reference__c = member1.name;
        myPayload.notifiers.add(notifier1);
        
        Challenge_Category__c category1 = new Challenge_Category__c();
        category1.category__c = cat1.id;
        myPayload.categories.add(category1);
        
        Challenge_Prize__c prize1 = new Challenge_Prize__c();
        prize1.place__c = 1;
        prize1.points__c = 1000;
        prize1.prize__c = '$1000.00';
        prize1.value__c = 1000.00;

        Challenge_Prize__c prize2 = new Challenge_Prize__c();
        prize2.place__c = 2;
        prize2.points__c = 500;
        prize2.prize__c = '$500.00';
        prize2.value__c = 500.00;

        Challenge_Prize__c prize3 = new Challenge_Prize__c();
        prize3.place__c = 3;
        prize3.points__c = 200;
        prize3.prize__c = '$200.00';
        prize3.value__c = 200.00;     
        
        myPayload.prizes.add(prize1);  
        myPayload.prizes.add(prize2);  
        myPayload.prizes.add(prize3);           
        
        Challenge_Reviewer__c reviewer1 = new Challenge_Reviewer__c();
        reviewer1.Member_Reference__c = member1.name;
        myPayload.reviewers.add(reviewer1);
        
        //Serialize the object
        string jsonPayload = JSON.serialize(myPayload);
        
        System.debug('------------------- Serialized payload JSON format: ' + jsonPayload);

        //Create the rest request and send it with the json data.
        RestRequest req = new RestRequest(); 
        RestResponse res = new RestResponse();
        
        
        req.httpMethod = 'POST';
        req.requestBody = blob.valueOf(jsonPayload);
        
        system.debug('---------------------- Request Bod');
        system.debug(req.requestBody);
        string createChallenge = doPost(req,res);
        system.debug('------------------- Created Challenge. Result is: ' + createChallenge); 
        
        //Get the challenge we just created, and it's related objects.
        list<Challenge__c> assertChallengeCreate = [select id, 
                                                    (select id, member__c from Challenge_Reviewers__r),
                                                    (select id from Challenge_Categories__r),
                                                    (select id from Challenge_Prizes__r),
                                                    (select id, member__c from Challenge_Comment_Notifiers__r)
                                                    from challenge__c where challenge_id__c = '001231231232'];
        
        //Verify the challenge got created
        system.assertEquals(1,assertChallengeCreate.size());
        
        //Verify the categories got attached
        system.assertEquals(myPayload.categories.size(),assertChallengeCreate[0].Challenge_Categories__r.size());
        
        //Verify the prizes got attached
        system.assertEquals(myPayload.prizes.size(),assertChallengeCreate[0].Challenge_Prizes__r.size());
        
        //Verify the notifiers got attached
        system.assertEquals(myPayload.notifiers.size(),assertChallengeCreate[0].Challenge_Comment_Notifiers__r.size());
        
        //Verfiy the reviewers got attached
        system.assertEquals(myPayload.reviewers.size(),assertChallengeCreate[0].Challenge_Reviewers__r.size());
        
        //Verify the reviewer record got properly attached to it's member
         system.assertEquals(member1.id,assertChallengeCreate[0].Challenge_Reviewers__r[0].member__c);

        //Verify the comment notifier record got properly attached to it's member
         system.assertEquals(member1.id,assertChallengeCreate[0].Challenge_Comment_Notifiers__r[0].member__c);              
    }
}