Java 使用GSON修改json而不使用POJO
我想修改json内容而不将其转换为POJO。我正在使用GSON图书馆 以下是用例:Java 使用GSON修改json而不使用POJO,java,json,gson,Java,Json,Gson,我想修改json内容而不将其转换为POJO。我正在使用GSON图书馆 以下是用例: String jsonString = "[{\"key1\":\"Hello\",\"key2\":\"World\"},{\"key1\":\"Nice\",\"key2\":\"Town\"}]"; JsonElement jsonElement = gson.fromJson(jsonString, JsonElement.class); 是否有任何方法可以在每个数组中将key1的值设置为某
String jsonString = "[{\"key1\":\"Hello\",\"key2\":\"World\"},{\"key1\":\"Nice\",\"key2\":\"Town\"}]";
JsonElement jsonElement = gson.fromJson(jsonString, JsonElement.class);
是否有任何方法可以在每个数组中将key1的值设置为某个值(比如说“Test”),而无需将内容转换为POJO一种方法是将JSON转换为
java.util.Map
,修改映射,然后从那里开始(这可能意味着将映射序列化回JSON)
这种方法符合我的偏好,即为正确的作业使用正确的API,最大限度地减少使用像Gson这样的工具来处理序列化/反序列化(据我所知,这就是它的设计目的)。也就是说,不要将Gson API用作替换数据结构。Gson有两个单独的API(可以组合):一个用于序列化和反序列化,另一个用于流式处理。如果希望在不增加内存开销的情况下处理JSON流,或者使用动态结构(而不是静态POJO),可以执行以下操作:
public class Whatever {
static void streamandmodify(JsonReader reader, JsonWriter writer) throws IOException {
while (true) {
JsonToken token = reader.peek();
switch (token) {
// most cases are just consume the event
// and pass an identical one to the writer
case BEGIN_ARRAY:
reader.beginArray();
writer.beginArray();
break;
case END_ARRAY:
reader.endArray();
writer.endArray();
break;
case BEGIN_OBJECT:
reader.beginObject();
writer.beginObject();
// this is where the change happens:
writer.name("test");
writer.value(1);
break;
case END_OBJECT:
reader.endObject();
writer.endObject();
break;
case NAME:
String name = reader.nextName();
writer.name(name);
break;
case STRING:
String s = reader.nextString();
writer.value(s);
break;
case NUMBER:
String n = reader.nextString();
writer.value(new BigDecimal(n));
break;
case BOOLEAN:
boolean b = reader.nextBoolean();
writer.value(b);
break;
case NULL:
reader.nextNull();
writer.nullValue();
break;
case END_DOCUMENT:
return;
}
}
}
public static void main(String[] args) throws IOException {
// just for test:
JsonReader jr = new JsonReader(new StringReader("{\"a\":1, \"b\":{\"c\":[1,2,3,{},{}]}}"));
StringWriter sw = new StringWriter();
JsonWriter jw = new JsonWriter(sw);
streamandmodify(jr, jw);
System.out.println(sw.getBuffer().toString());
}
}
- 创建一个JsonWriter(在我的示例中,我使用StringWriter)李>
- 创建一个JsonReader李>
- 创建一个循环,使用来自读者的事件并将其提供给作者,可能进行更改、添加、省略等
public class Whatever {
static void streamandmodify(JsonReader reader, JsonWriter writer) throws IOException {
while (true) {
JsonToken token = reader.peek();
switch (token) {
// most cases are just consume the event
// and pass an identical one to the writer
case BEGIN_ARRAY:
reader.beginArray();
writer.beginArray();
break;
case END_ARRAY:
reader.endArray();
writer.endArray();
break;
case BEGIN_OBJECT:
reader.beginObject();
writer.beginObject();
// this is where the change happens:
writer.name("test");
writer.value(1);
break;
case END_OBJECT:
reader.endObject();
writer.endObject();
break;
case NAME:
String name = reader.nextName();
writer.name(name);
break;
case STRING:
String s = reader.nextString();
writer.value(s);
break;
case NUMBER:
String n = reader.nextString();
writer.value(new BigDecimal(n));
break;
case BOOLEAN:
boolean b = reader.nextBoolean();
writer.value(b);
break;
case NULL:
reader.nextNull();
writer.nullValue();
break;
case END_DOCUMENT:
return;
}
}
}
public static void main(String[] args) throws IOException {
// just for test:
JsonReader jr = new JsonReader(new StringReader("{\"a\":1, \"b\":{\"c\":[1,2,3,{},{}]}}"));
StringWriter sw = new StringWriter();
JsonWriter jw = new JsonWriter(sw);
streamandmodify(jr, jw);
System.out.println(sw.getBuffer().toString());
}
}
jsonString是一个普通的Java字符串;因此,您可以使用Java的标准字符串函数对其进行任意修改,并将子字符串
key1
替换为Test1
:
jsonString = "[{\"key1\":\"Test\",\"key2\":\"World\"},{\"key1\":\"Nice\",\"key2\":\"Town\"}]";
当然,Java中的字符串是不可变的,因此首先将其转换为StringBuilder可能会在内存使用方面给您带来更好的性能。您总是可以获得不同于JsonElement的类型,或者使用JsonElement.getAsJsonObject强制转换为对象(如果可能)
我之前错了;似乎没有JsonArray适配器;您必须获得一个JsonElement并使用铸造工具。这是我想出的最短的
JsonElement je = new Gson().fromJson(jsonString, JsonElement.class);
JsonObject jo = je.getAsJsonObject();
jo.add("key", value);
一旦有了JsonObject,gson就有很多方法来操作它。使用gson JsonArray Java 8修改json 如何使用GSON修改JSON中的值的示例
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class ModifyJson {
public static void main(String[] args) {
String data = "[{\"ct_pk\":24,\"ct_name\":\"SISTEMA DE PRUEBAS\"},"
+ "{\"ct_pk\":1,\"ct_name\":\"CAPITAL FEDERAL\"}," +
"{\"ct_pk\":5,\"ct_name\":\"SISTEMA DE PRUEBAS DOS\"}]";
System.out.println("before................." + data);
JsonArray jsonArray = new Gson().fromJson(data, JsonElement.class).getAsJsonArray();
JsonArray jsonArray2 = new JsonArray();
for (JsonElement pa : jsonArray) {
JsonObject jsonObject2 = pa.getAsJsonObject();
String ct_name = jsonObject2.get("ct_name").getAsString();
if (ct_name.equals("SISTEMA DE PRUEBAS")) {
jsonObject2.addProperty("ct_name", "TODOS");
}
jsonArray2.add(jsonObject2);
}
System.out.println("after.................." +jsonArray2);
}
}
在测试代码中,这是一个不错的黑客策略,但如果原始或字符串或替换项由用户提供,则在生产中要小心。JavaScript(以及扩展的JSON)在处理转义和特殊字符方面相当复杂。您可能想让一个经过良好测试的库在生产中编辑JSON。可能您的问题搞错了。我感兴趣的是修改key1的值,而不是key1本身。在第一种情况下,key1的值是Hello,我想修改它;这只是一个必须改变的例子。我认为,进一步讨论没有意义。如果你的答案保持不变,那么我无法管理动态值,它可以是任何东西,而我不知道用什么和什么时间替换什么。这是个坏主意。非常糟糕的主意。你将如何将JSON转换为Map?这是JsonWriter可以做的很好的例子,这是肯定的。但是对于OP的任务,没有理由通过流而不是使用经过良好测试的gson.fromJson()来重新创建JSON对象。看看杰夫的回答。@teejay:“没有理由”?你怎么知道?为什么会有这样的评论?我可以找到一些很好的理由,不构建一个任意大的JSON文档的完整内存表示,而只是为了添加一些属性,比如说,将整个内容序列化回一个文件。我们都不知道问题的来龙去脉,所以streamish和domish两种方法似乎都更好。好吧,我假设提交到这个页面的人想要解决他们的问题——即从他们已经完全可用的字符串修改JSON(=没有理由流式处理)。你的答案“有效”,但在另一种情况下更合适。无意冒犯:)@teejay:我知道你是“人民”的声音?从作者的脑海中读出问题的确切背景?那么,在这种情况下,我很抱歉写了这样一个答案,不会再发生了。但请允许我为自己辩护:在我居住的陌生地方,Java应用程序主要使用JSON与外部系统通信,使用网络或文件。我使用的java.io和javax.servlet包的奇特版本中包含一些方法,这些方法使数据以字符串形式弹出到内存中,这迫使我使用流。我真的,真的以为我不是一个人。我知道你是流媒体的人:)我们只是“默认”假设不同的上下文,没关系。只是想知道这种方法的缺点是什么。。你在表现上有过问题吗?还是输出JSON无效?你有单元测试吗?迁移到较新的GSON版本怎么样,至少有一点未来的证据吗?请发布完整的解决方案,我不明白GSON对象是如何创建的?请投票支持阵列解决方案。请在您的答案中更新循环。