[SalesForce] Writing JSON using JSONGenerator with writeStringField()

I'm wondering why I can't use the method writeStringField() on the class variables below. I'm using the JSONGenerator class methods instead of hand-constructing the string.

global class VF_MethodRegister {

   public boolean hasCreditCard{get;set;}
   public String cardNumber{get;set;}
   public Integer cardMonth{get;set;}
   public Integer cardYear{get;set;}
   public String cardCVC{get;set;}
   public String email{get;set;}
   public String descr{get;set;}

String kt = ApexPages.currentPage().getParameters().get('kt');
public String message {get;set;}
private final Contact thisCon;

public VF_MethodRegister(ApexPages.StandardController stdController) {
    this.thisCon = (Contact)stdController.getRecord();
}

public VF_MethodRegister(){}

public void registerCustomer(){
    HttpRequest req = new HttpRequest();
    HttpResponse res = new HttpResponse();
    Http h = new Http();    

    Oauth_Settings__c endo = Oauth_Settings__c.getValues('Method_Reg');   // get the    endpoint from custom settings
    String endp = endo.Endpoint__c;

    JSONGenerator jgen = JSON.createGenerator(true);
    jgen.writeStartObject();
    jgen.writeFieldName('Card');
    jgen.writeStartArray();
    jgen.writeStringField('number', cardNumber);   //this line fails upon running
    jgen.writeNumberField('month',cardMonth);
    jgen.writeNumberField('year', cardYear);
    jgen.writeStringField('CVC', cardCVC);
    jgen.writeEndArray();
    jgen.writeStringField('PersonalID', kt);
    jgen.writeStringField('email', email);
    jgen.writeStringField('RegistrationFrom', 'apex');
    jgen.writeEndObject();

I see whem running the debug logs that the values for these variables are set correctly from the page that uses the Extension. But the error I get is Can not write a field name, expecting a value for this line:

 jgen.writeStringField('number', cardNumber); 

I've tried also to use jgen.writeStringField('number', cardNumber.toString()); but that didn't work.

What would be the correct method of getting the values from the class variables into the JSON? Other than hand-constructing the string (my first time using the JSONGenerator class).

Best Answer

Rather than manually constructing the JSON, providing the names you need to use in the JSON are legal Apex identifiers you can leave it to the platform to build the correct serialization and just use simple Apex classes:

global class VF_MethodRegister {

    public class Message {
        public Item[] Card;
        public String PersonalID;
        public String email;
        public String RegistrationFrom;
    }

    public class Item {
        public String number;
        public Integer month;
        public Integer year;
        public String CVC;
    }

    private statuc String toJsonString(Message m) {
        return JSON.serializePretty(m);
    }

In your case you would have to transfer the values from the class fields to these simple objects first.