json 转 javaBean

前言:经常在网络上看见一些关于json自动转换成javaBean的jar包,项目组里的人也在用,稍稍研究了下,都是用的反射来做的。我细细想了下里面的逻辑,我觉得直接生成JavaBean代码岂不是更加直接,反射在移动端,怎么说都是消耗资源的。

Java Bean 类的结构

首先要梳理下,到底Bean类是一个什么样的文件,很简单的是有很多属性的class文件,属性有很多类别,但是从json的角度来看,类别又是有限的:基本类型和List。我们可以用python来模拟下:

# encoding: utf-8
'''
Created on 2014.12.24

@author: 13051041
'''

class JavaClass(object):
    '''
    class templete
    '''
    def __init__(self, name):
        '''
        Constructor
        '''
        self.mName = name;
        self.mIntegerList = []
        self.mStrList = []
        self.mBolList = []
        self.mListList = []
        self.mClassList = []
        self.mInClassTypeList = []
        self.mIsParcelable = True
        self.mPackageName = "package com.codegenerator;"
    
    def addIntAttribute(self, str1):
        '''
        add String attribute
        '''
        self.mIntegerList.append(str1)
    
    def addUnicodeAttribute(self, str1):
        '''
        add String attribute
        '''
        self.mStrList.append(str1)
         
    
    def addBooleanAttribute(self, bol):
        '''
        add Boolean attribute
        '''
        self.mBolList.append(bol)
         
    
    def addListAttribute(self, list1):
        '''
        add List attribute
        '''
        self.mListList.append(list1)
         
    
    def addClassAttribute(self, cls):
        '''
        add Class attribute
        '''
        self.mClassList.append(cls)
         
    
    def addInClassType(self, inClass):
        '''
        add Inner Class attribute
        '''
        self.mInClassTypeList.append(inClass)
         

    def test(self):
        print "-----this is JavaClass information start-----"
        print "class's name is %s" % self.mName
        print "class's integer is %s " % self.mIntegerList
        print "class's String is %s " % self.mStrList
        print "class's Boolean is %s " % self.mBolList
        print "class's List is %s " % self.mListList
        print "class's inner class is %s " % self.mClassList
        print "class's inner class type is %s " % self.mInClassTypeList
        print "-----this is JavaClass information end-----"

classNum = 0   
def autoGeneratorClassName():
    global classNum
    classNum = classNum + 1
    return "class%d" % classNum

def buildJavaClassNode(jsonObject, className):
    javaclass = JavaClass(className)
    keys = jsonObject.keys()
    for key in keys:
        t = type(jsonObject[key])
        if t == int:
            javaclass.addIntAttribute(key)
        if t == unicode:
            javaclass.addUnicodeAttribute(key)
        if t == bool:
            javaclass.addBooleanAttribute(key)
        if t == dict:
            newClassName = autoGeneratorClassName() 
            javaclass.addClassAttribute((newClassName, key))
            javaclass.addInClassType(buildJavaClassNode(jsonObject[key], newClassName))
        if t == list:
            t2 = type(jsonObject[key][0])
            if t2 == dict:
                newClassName = autoGeneratorClassName() 
                javaclass.addListAttribute((newClassName, key))
                javaclass.addInClassType(buildJavaClassNode(jsonObject[key][0], newClassName))
            else:
                javaclass.addListAttribute((t2, key))
            

    return javaclass

  

生成java文件,递归才是王道

我们一个叫javaclass的python类了,用python读取json,直接生成实例。现在的任务是把这个实例,写到文件里面。想想class的嵌套关系,生成最好的方法就是递归:

# encoding: utf-8
'''
Created on 2014.12.26

@author: 13051041
'''

Class_import = '''
%s

import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;
'''

Class_import_parcelable = '''
import android.os.Parcel;
import android.os.Parcelable;
'''

Class_HEAD = '''
public %s class %s { 
'''

Class_HEAD_parcelable = '''
public %s class %s implements Parcelable{
    public %s() {
      }
       
    public  %s(Parcel in) {
    readFromParcel(in);
    }  
'''

Class_Method_END = "}
"

Attribute_TEMP = "public %s %s;
"

Method_Analyzer = '''
    public void analyzerJson(JSONObject jsonObject) throws JSONException {
        if(jsonObject == null){
            return;
        }
'''


Method_TEMP = "public %s %s(%s)throws JSONException {
"
Method_GET_INT = '''%s = GetJsonAttributeUtil.getInt(jsonObject, "%s");'''
Method_GET_String = '''%s = GetJsonAttributeUtil.getString(jsonObject,"%s");'''
Method_GET_Boolean = '''%s = GetJsonAttributeUtil.getBoolean(jsonObject,"%s");'''
Method_GET_CLASS = '''%s = new %s();
                      %s.analyzerJson(GetJsonAttributeUtil.getJSONObject(jsonObject,"%s"));'''
Method_GET_List = '''
    %s= new ArrayList<%s>();
    JSONArray array%s = GetJsonAttributeUtil.getJSONArray(jsonObject,"%s");
    int %sLen = array%s.length();
    for(int i = 0;i<%sLen;i++){
         %s item = new %s();
         item.analyzerJson(array%s.getJSONObject(i));
         %s.add(item);
    }
'''

Method_Parcelable_Write = '''public void writeToParcel(Parcel dest, int flags) {
 '''
Mehtod_Parcelable_Value_Write = "dest.write%s(%s);
"
Method_Parcelable_Read = '''public void readFromParcel(Parcel in) {
 '''
Mehtod_Parcelable_Value_Read = "%s= in.readString();  "


IS_PARCELABLE = True
FILE_NAME = "Bean"

def writeParcelabelMethod(f, jcls):
    # writeToParcel method
    f.write(Method_Parcelable_Write)
    for attribute in jcls.mIntegerList:
        f.write("dest.writeInt(%s);
" % (attribute))
    for attribute in jcls.mStrList:
        f.write("dest.writeString(%s);
" % (attribute))
    for attribute in jcls.mBolList:
        f.write("dest.writeByte((byte) (%s ? 1 : 0));
" % (attribute))
            
    for attribute in jcls.mListList:
        f.write("dest.writeTypedList(%s);" % (attribute[1]))
            
    for attribute in jcls.mClassList:
        f.write("dest.writeParcelable(%s, PARCELABLE_WRITE_RETURN_VALUE);" % attribute[1])
            
    f.write(Class_Method_END)
        
    # readFromParcel method
    f.write(Method_Parcelable_Read)
    for attribute in jcls.mIntegerList:
        f.write("%s= in.readInt();
" % (attribute))
    for attribute in jcls.mStrList:
        f.write("%s= in.readString();
" % (attribute))
    for attribute in jcls.mBolList:
        f.write("%s = in.readByte() != 0;
" % (attribute))
    
    for attribute in jcls.mListList:
        f.write("%s = new ArrayList<%s>();" % (attribute[1], attribute[0]))
        f.write("in.readTypedList(%s, %s.CREATOR);" % (attribute[1], attribute[0]))
            
    for attribute in jcls.mClassList:
        f.write("%s = in.readParcelable(%s.class.getClassLoader());" % (attribute[1], attribute[0]))
            
    f.write(Class_Method_END)
    # describeContents method   
    f.write("public int describeContents() {return 0;}")
    
    f.write('''
          public static final Parcelable.Creator<%s> CREATOR = 
                new Parcelable.Creator<%s>() {
            public %s createFromParcel(Parcel in) {
                return new %s(in);
            }
    
            public %s[] newArray(int size) {
                return new %s[size];
            }
        };
        ''' % (jcls.mName, jcls.mName, jcls.mName, jcls.mName, jcls.mName, jcls.mName))
    
    pass


def writeCls2File(jcls, f):
    f.seek(0, 2)
    # write class header
    if IS_PARCELABLE:  # if need implement parcelable
        if jcls.mName == FILE_NAME:
            f.write(Class_HEAD_parcelable % ("", jcls.mName, jcls.mName, jcls.mName))
        else:
            f.write(Class_HEAD_parcelable % ("static", jcls.mName, jcls.mName, jcls.mName))
    else:
        f.write(Class_HEAD % ("", jcls.mName))
    
    
    # write class's attribute
    for attribute in jcls.mIntegerList:
        f.write(Attribute_TEMP % ('int', attribute))
    for attribute in jcls.mStrList:
        f.write(Attribute_TEMP % ('String', attribute))
    for attribute in jcls.mBolList:
        f.write(Attribute_TEMP % ('Boolean', attribute))
    for attribute in jcls.mListList:
        f.write(Attribute_TEMP % ('List<' + attribute[0] + '>', attribute[1]))
    for attribute in jcls.mClassList:
        f.write(Attribute_TEMP % (attribute[0], attribute[1]))
        
    # write class's method analyzerJson
    f.write(Method_Analyzer)
    for attribute in jcls.mIntegerList:
        f.write(Method_GET_INT % (attribute, attribute))
    for attribute in jcls.mStrList:
        f.write(Method_GET_String % (attribute, attribute))
    for attribute in jcls.mBolList:
        f.write(Method_GET_Boolean % (attribute, attribute))
    for attribute in jcls.mClassList:
        f.write(Method_GET_CLASS % (attribute[1], attribute[0], attribute[1], attribute[1]))
    for attribute in jcls.mListList:
        f.write(Method_GET_List % (attribute[1], attribute[0], attribute[1], attribute[1], attribute[1], attribute[1], attribute[1], attribute[0], attribute[0], attribute[1], attribute[1]))
    f.write(Class_Method_END)
    
    # write parcelable method
    if IS_PARCELABLE:
        writeParcelabelMethod(f, jcls)
        
    # the method toString
    f.write("public String toString(){")
    f.write("String allInfo = ")
    for attribute in jcls.mIntegerList:
        f.write(''' " %s="+%s +  ''' % (attribute, attribute))
    for attribute in jcls.mStrList:
        f.write(''' " %s="+%s +  ''' % (attribute, attribute))
    for attribute in jcls.mBolList:
        f.write(''' " %s="+%s +  ''' % (attribute, attribute))

    for attribute in jcls.mListList:
        f.write(''' " %s="+%s.toString() +  ''' % (attribute[1], attribute[1]))
    
    for attribute in jcls.mClassList:
        f.write(''' " %s="+%s.toString() +  ''' % (attribute[1], attribute[1]))
        
    f.write('''" ";''')
    f.write("return allInfo;")
    f.write(Class_Method_END)
    
    # write class's class
    for innerClass in jcls.mInClassTypeList:
        writeCls2File(innerClass, f)
        pass
    f.write(Class_Method_END)
    pass

def generatorClsFile(jcls):
    global IS_PARCELABLE
    global FILE_NAME
    IS_PARCELABLE = jcls.mIsParcelable
    FILE_NAME = jcls.mName
    f = open(FILE_NAME + ".java", 'w')
    f.write(Class_import % jcls.mPackageName)
    if IS_PARCELABLE:
        f.write(Class_import_parcelable)
    writeCls2File(jcls, f)

  完整项目:http://files.cnblogs.com/files/chenjie0949/CodeGenerator1.3.zip

原文地址:https://www.cnblogs.com/chenjie0949/p/4815640.html