Skip to content

Commit

Permalink
feat: support json readpath function
Browse files Browse the repository at this point in the history
  • Loading branch information
飞澋 authored and yndu13 committed Jan 16, 2025
1 parent 3cece40 commit 5f4bdeb
Show file tree
Hide file tree
Showing 8 changed files with 524 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test_csharp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ defaults:
jobs:
build:

runs-on: ubuntu-latest
runs-on: ubuntu-20.04

steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_java.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
matrix:
# test against latest update of each major Java version, as well as specific updates of LTS versions:
# 20, 21还不支持,报错是Source option 7 is no longer supported. Use 8 or later.
java: [7, 8, 11, 17]
java: [8, 11, 17]
fail-fast: false

steps:
Expand Down
79 changes: 79 additions & 0 deletions csharp/core/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,85 @@ public static string ToJSONString(object value)
}
return JsonConvert.SerializeObject(value);
}

/**
* Transform input as map.
*/
public static Dictionary<string, object> ParseToMap(object input)
{
if (input == null)
{
return null;
}

Type type = input.GetType();
var map = (Dictionary<string, object>)TeaModelExtensions.ToMapFactory(type, input);

return map;
}

public static object ReadPath(object obj, string path)
{
var jsonStr = ToJSONString(ParseToMap(obj));
var result = JObject.Parse(jsonStr).SelectToken(path);
return ConvertNumber(result);
}

private static object ConvertNumber(object input)
{
if (input == null) return null;

var token = input as JToken;
if (token != null)
{
if (token.Type == JTokenType.Integer)
{
return token.ToObject<long>();
}
if (token.Type == JTokenType.Float)
{
return token.ToObject<double>();
}
if (token.Type == JTokenType.String)
{
return token.ToString();
}
if (token.Type == JTokenType.Array)
{
return HandleList(token.Children());
}
if (token.Type == JTokenType.Object)
{
return HandleMap(token.ToObject<Dictionary<string, object>>());
}
if (token.Type == JTokenType.Boolean)
{
return token.ToObject<bool>();
}
}

return input;
}

private static object HandleList(IEnumerable<JToken> list)
{
var convertedList = new List<object>();
foreach (var item in list)
{
convertedList.Add(ConvertNumber(item));
}
return convertedList;
}

private static object HandleMap(IDictionary<string, object> map)
{
var convertedMap = new Dictionary<string, object>();
foreach (var entry in map)
{
convertedMap[entry.Key] = ConvertNumber(entry.Value);
}
return convertedMap;
}

public static bool Empty(string val)
{
Expand Down
179 changes: 178 additions & 1 deletion csharp/tests/CommonTest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AlibabaCloud.TeaUtil;
Expand Down Expand Up @@ -483,6 +484,182 @@ public void Test_AssertAsArray()

Assert.Throws<ArgumentException>(() => { Common.AssertAsArray("test"); });
}

[Fact]
public void Test_ParseToMap()
{
Assert.Null(Common.ParseToMap(null));

var context = new Context
{
Str = "test",
ContextInteger = 123,
ContextLong = 123L,
ContextDouble = 1.123d,
ContextFloat = 3.456f,
ContextListLong = new List<long?> { 123L, 456L },
ListList = new List<List<int?>>
{
new List<int?> { 789, 123 },
new List<int?> { 8, 9 }
},
IntegerListMap = new Dictionary<string, List<int?>>
{
{ "integerList", new List<int?> { 123, 456 } }
}
};

var dicModel = Common.ParseToMap(context);

Assert.Equal("test", dicModel["testStr"]);
Assert.Equal(123, ((List<object>)((Dictionary<string, object>)dicModel["integerListMap"])["integerList"])[0]);
Assert.Equal(new List<int?> { 789, 123 }, ((List<object>)dicModel["listList"])[0]);

Dictionary<string, object> dic = new Dictionary<string, object>
{
{ "model", context }
};

var dicMap = Common.ParseToMap(dic);

Assert.Equal(dicModel, dicMap["model"]);
}

[Fact]
public void Test_ReadPath()
{
var context = new Context
{
Str = "test",
TestBool = true,
ContextInteger = 123,
ContextLong = 123L,
ContextDouble = 1.123d,
ContextFloat = 3.456f,
ContextListLong = new List<long?> { 123L, 456L },
ListList = new List<List<int?>>
{
new List<int?> { 789, 123 },
new List<int?> { 8, 9 }
},
IntegerListMap = new Dictionary<string, List<int?>>
{
{ "integerList", new List<int?> { 123, 456 } }
}
};

Assert.Null(Common.ReadPath(context, "$.notExist"));
Assert.True(Common.ReadPath(context, "$.testBool") is bool);
Assert.True(Common.ReadPath(context, "$.listList") is List<object>);
Assert.True(Common.ReadPath(context, "$.contextInteger") is long);
Assert.True(Common.ReadPath(context, "$.contextLong") is long);
Assert.True(Common.ReadPath(context, "$.contextDouble") is double);
Assert.True(Common.ReadPath(context, "$.contextFloat") is double);
Assert.True(Common.ReadPath(context, "$.contextListLong") is List<object>);
Assert.True(Common.ReadPath(context, "$.integerListMap") is Dictionary<string, object>);

Assert.Equal(true, Common.ReadPath(context, "$.testBool"));
Assert.Equal("test", Common.ReadPath(context, "$.testStr"));
Assert.Equal(123L, Common.ReadPath(context, "$.contextLong"));
var listLong = Common.ReadPath(context, "$.contextListLong") as List<object>;
Assert.Equal(123L, listLong[0]);

var listList = Common.ReadPath(context, "$.listList") as List<object>;
Assert.Equal(789L, (listList[0] as List<object>)[0]);

var map = Common.ReadPath(context, "$.integerListMap") as Dictionary<string, object>;
Assert.Equal(123L, (map["integerList"] as List<object>)[0]);

var realListList = new List<List<int?>>();
foreach (var itemList in listList)
{
var intList = itemList as List<object>;
var nullableIntList = new List<int?>();
if (intList != null)
{
foreach (var item in intList)
{
var intValue = (int?)(item as long?);
nullableIntList.Add(intValue);
}
}

realListList.Add(nullableIntList);
}


var realIntegerListMap = new Dictionary<string, List<int?>>();
foreach (var kvp in map)
{
string key = kvp.Key;
object value = kvp.Value;

var intList = value as List<object>;
var nullableIntList = new List<int?>();
if (intList != null)
{
foreach (var item in intList)
{
nullableIntList.Add((int?)(item as long?));
}
}
realIntegerListMap[key] = nullableIntList;
}
var context1 = new Context
{
ContextLong = Common.ReadPath(context, "$.contextLong") as long?,
ContextInteger = (int?)(Common.ReadPath(context, "$.contextInteger") as long?),
ContextFloat = (float?)(Common.ReadPath(context, "$.contextFloat") as double?),
ContextDouble = Common.ReadPath(context, "$.contextDouble") as double?,
ContextListLong = (Common.ReadPath(context, "$.contextListLong") as List<object>)
.Select(item => item is long longValue ? longValue : (long?)null)
.ToList(),
ListList = realListList,
IntegerListMap = realIntegerListMap
};

Assert.Equal(123L, context1.ContextLong);
Assert.Equal(123, context1.ContextInteger);
Assert.Equal(3.456f, context1.ContextFloat);
Assert.Equal(1.123d, context1.ContextDouble);
Assert.Equal(new List<long?> { 123L, 456L }, context1.ContextListLong);
Assert.Equal(new List<List<int?>>
{
new List<int?> { 789, 123 },
new List<int?> { 8, 9 }
}, context1.ListList);
Assert.Equal(123, (context1.IntegerListMap["integerList"] as List<int?>)[0]);
}
}

public class Context : TeaModel
{
[NameInMap("testStr")]
public string Str { get; set; }

[NameInMap("testBool")]
public bool? TestBool { get; set; }

[NameInMap("contextInteger")]
public int? ContextInteger { get; set; }

[NameInMap("contextLong")]
public long? ContextLong { get; set; }

[NameInMap("contextListLong")]
public List<long?> ContextListLong { get; set; }

[NameInMap("listList")]
public List<List<int?>> ListList { get; set; }

[NameInMap("contextDouble")]
public double? ContextDouble { get; set; }

[NameInMap("contextFloat")]
public float? ContextFloat { get; set; }

[NameInMap("integerListMap")]
public Dictionary<string, List<int?>> IntegerListMap { get; set; }
}

public class TestRegModel : TeaModel
Expand Down Expand Up @@ -539,4 +716,4 @@ public class TestRegSubModel : TeaModel

public int? testInt { get; set; }
}
}
}
9 changes: 7 additions & 2 deletions java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>

<build>
Expand All @@ -78,8 +83,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>7</source>
<target>7</target>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
Expand Down
45 changes: 45 additions & 0 deletions java/src/main/java/com/aliyun/teautil/Common.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.aliyun.teautil.models.TeaUtilException;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import com.jayway.jsonpath.JsonPath;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
Expand Down Expand Up @@ -75,6 +76,50 @@ public static Object parseJSON(String json) {
}.getType());
}

public static Map<String, Object> parseToMap(Object o) {
if (null == o) {
return null;
}
return (Map<String, Object>) TeaModel.parseObject(o);
}

public static <T> T readPath(Object json, String path) {
String jsonStr = toJSONString(parseToMap(json));
Object result = JsonPath.read(jsonStr, path);
return (T) convertNumber(result);
}


private static Object convertNumber(Object input) {
if (input instanceof Integer) {
return Long.valueOf((Integer) input);
} else if (input instanceof List) {
List<?> list = (List<?>) input;
return handleList(list);
} else if (input instanceof Map) {
Map<?, ?> map = (Map<?, ?>) input;
return handleMap(map);
}
return input;
}

private static List<?> handleList(List<?> list) {
List<Object> longList = new ArrayList<>();
for (Object item : list) {
longList.add(convertNumber(item));
}
return longList;
}

private static Map<String, ?> handleMap(Map<?, ?> map) {
Map<String, Object> longMap = new LinkedHashMap<>();
for (Map.Entry<?, ?> entry : map.entrySet()) {
String key = (String) entry.getKey();
longMap.put(key, convertNumber(entry.getValue()));
}
return longMap;
}

/**
* Assert a value, if it is a map, it, otherwise throws
*
Expand Down
Loading

0 comments on commit 5f4bdeb

Please sign in to comment.