将平面JSON结构转换为对象并添加另一个属性

时间:2018-05-10 21:17:22

标签: java json

我有一个保存在json中的简单对象我想转换回对象并同时添加一个新属性:

json字符串是这样的:

{"Database":0,"SalesForce":0,"Watson":0,"AIC":0,"Luise":0}

我想补充一下:

"Total":0

所以我回来的对象应该是:

class myObj{
    private int Database;
    private int SalesForce;
    private int Watson;
    private int AIC;
    private int Luise;
    private int Total;
}

我没有实际的课程,我想动态地这样做。 IE,作为动态对象。

1 个答案:

答案 0 :(得分:0)

由于问题是如何将JSON结构转换为添加另一个属性的对象而不是如何修改原始JSON字符串,我想发布一个答案,该答案实际上做了问题的标题:JSON to Java对象转换。

以下代码仅在没有嵌套对象时才有效,如果JSON结构很大(由于字符串连接),则效率不高。

另外,请注意动态创建类可能不是一个好主意(例如讨论here)。但是,如果您需要,可以在下面给出一个可能的解决方案。在此解决方案中,JSON字符串将转换为Map并添加新的键值对。然后编写和编译目标类的源代码,加载类并调用测试方法用于演示目的。

import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;


public class JsonToJava

{
    private static Map<String, Object> map;
    private static  String json = "{\"Database\":0,\"SalesForce\":0,\"Watson\":0,\"AIC\":0,\"Luise\":0}";
    private static String fileName = "Test";

    public static void main(String[] args) throws Exception {

        // create an empty source file
        File sourceFile = File.createTempFile(fileName, ".java");
        sourceFile.deleteOnExit();

        java.lang.reflect.Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
        Gson gson = new Gson();
        map = gson.fromJson(json, mapType );

        addProperty( "Total", "0" );

        String fields = "";

        for (Map.Entry<String, Object> entry : map.entrySet())
        {
            fields += "\tprivate " ;
            try{
                Double.parseDouble( entry.getValue().toString() );
                fields += "double ";
            }
            catch ( NumberFormatException e ){
                try{
                    Integer.parseInt( entry.getValue().toString() );
                    fields += "int ";
                }
                catch ( NumberFormatException ex ){
                    fields += "String " + entry.getValue();
                }
            }
            fields += entry.getKey() + ";\n";
        }

        // generate the source code
        String classname = sourceFile.getName().split("\\.")[0];
        String sourceCode = "public class " + classname + "{\n\n" +
                 fields +
                "\n\tpublic void hello(){\n\t\t System.out.print(\"Hello world\");\n\t}\n}";

        // write the source code into the source file
        System.out.println(sourceCode);
        FileWriter writer = new FileWriter(sourceFile);
        writer.write(sourceCode);
        writer.close();

        // compile the source file
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        File parentDirectory = sourceFile.getParentFile();
        fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singletonList( parentDirectory ) );
        Iterable<? extends JavaFileObject> compilationUnits =
                fileManager.getJavaFileObjectsFromFiles( Collections.singletonList( sourceFile ) );
        compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
        fileManager.close();

        // load the class
        URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { parentDirectory.toURI().toURL() });
        Class<?> helloClass = classLoader.loadClass(classname);

        // call a method of the newly compiled and loaded class
        Method helloMethod = helloClass.getDeclaredMethod("hello");
        helloMethod.invoke(helloClass.newInstance());
    }

    private static void addProperty(String key, String value)
    {
        map.put( key, value );
    }
}