Câu hỏi Freemarker lặp lại qua các khóa băm


Freemarker có hai bộ sưu tập kiểu dữ liệu, danh sách và hashmaps Có cách nào để lặp qua các khóa hashmap giống như chúng ta làm với các danh sách không?

Vì vậy, nếu tôi có một var với dữ liệu cho phép nói:

user : {
  name : "user"
  email : "looser@everything.com"
  homepage : "http://nosuchpage.org"
}

Tôi muốn in tất cả các thuộc tính của người dùng với giá trị của họ. Điều này không hợp lệ, nhưng mục tiêu là rõ ràng:

<#list user.props() as prop>
  ${prop} = ${user.get(prop)}
</#list>

76
2017-09-30 12:22


gốc




Các câu trả lời:


Chỉnh sửa: Không sử dụng giải pháp này với FreeMarker 2.3.25 trở lên, đặc biệt là không .get(prop). Xem các câu trả lời khác.

Bạn sử dụng tích hợp sẵn phím chức năng, ví dụ: điều này sẽ hoạt động:

<#list user?keys as prop>
    ${prop} = ${user.get(prop)}
</#list>  

94
2017-09-30 12:27



cú pháp là khác nhau trong phiên bản mới nhất, như minh họa trong liên kết tôi đăng trong câu trả lời của tôi. Tôi nhận ra đây là một câu hỏi cũ, nhưng nó được xếp hạng cao trên Google. - Nick Spacek
chỉ là một lưu ý - bạn có thể sử dụng ${user[prop]} như một cách viết tắt - Bozho
Đây là một rò rỉ hiệu năng: cho mỗi khóa, nó cần lấy giá trị. Lặp lại các entrySet () không có vấn đề đó. - Geoffrey De Smet
phải là $ {user [prop]} - dns
Đó là $ {map [key]}, xem freemarker.org/docs/ref_builtins_hash.html - david_p


FYI, có vẻ như cú pháp để truy xuất các giá trị đã thay đổi theo:

http://freemarker.sourceforge.net/docs/ref_builtins_hash.html

<#assign h = {"name":"mouse", "price":50}>
<#assign keys = h?keys>
<#list keys as key>${key} = ${h[key]}; </#list>

47
2018-03-30 17:24



Cú pháp này khác nhau như thế nào? - Parker
Tôi nghĩ đó là .get không hoạt động nữa. - Nick Spacek
câu trả lời tốt ;-) lưu ý rằng bạn có thể phải thực hiện kiểm tra giá trị rỗng khi in giá trị của bạn, <#if h [key] ??> $ {key} = $ {h [key]}; </ # if> - Brad Parks
Cú pháp không thay đổi. Cả hai [key] và .get(key) tồn tại từ thời cổ đại. .get(key) không có gì đặc biệt đối với FTL, nó chỉ gọi phương thức Java công khai. Nhưng bạn chỉ có thể sử dụng nó nếu FreeMarker được cấu hình để lộ Map phương pháp. - ddekany
Khi lặp lại, tôi nhận được các phương thức (getClass, hashCode, equals, get, toString, class) ... tuy nhiên, tôi không thấy bất kỳ thuộc tính nào như 'id', đó là những gì tôi muốn nhận danh sách. Bất kỳ đề xuất làm thế nào để có được danh sách các thuộc tính không phương pháp từ băm đó? Tôi cần phải biết những tên tài sản đó. : | - MaxRocket


Kể từ 2.3.25, hãy làm như sau:

<#list user as propName, propValue>
  ${propName} = ${propValue}
</#list>

Lưu ý rằng điều này cũng hoạt động với các phím không phải chuỗi (không giống như map[key], mà phải được viết là map?api.get(key) sau đó).

Trước 2.3.25, dung dịch chuẩn là:

<#list user?keys as prop>
  ${prop} = ${user[prop]}
</#list>

Tuy nhiên, một số tích hợp FreeMarker cũ thực sự sử dụng cấu hình lạ, nơi công cộng Map phương pháp (như getClass) xuất hiện dưới dạng khóa. Điều đó xảy ra khi họ đang sử dụng một BeansWrapper (thay vì DefaultObjectWrapper) có simpleMapWrapper thuộc tính được để lại trên false. Bạn nên tránh thiết lập như vậy, vì nó trộn lẫn các phương thức với thực Map mục. Nhưng nếu bạn chạy vào thiết lập không may như vậy, cách để thoát khỏi tình huống là sử dụng các phương thức Java được tiếp xúc, chẳng hạn như user.entrySet(), user.get(key), v.v. và không sử dụng cấu trúc ngôn ngữ mẫu như ?keys hoặc là user[key].


24
2017-07-08 17:25



Điều này hoạt động hoàn hảo. Nhưng, tôi thấy lỗi trong IDE lò xo. Bất kỳ ý tưởng làm thế nào để có được nó cố định? Cảm ơn - harshavmb
@harshavmb Lỗi gì? Liệu nó có sử dụng một plugin FreeMarker lỗi thời có lẽ, mà đi kèm với một phiên bản FreeMarker cũ? - ddekany
Đừng nghĩ vậy. Đã tải xuống phiên bản mới nhất từ ​​các công cụ jboss. Tôi sẽ thử trên máy khác và cho bạn biết. - harshavmb
@harshavmb Nếu bạn nhập một cái gì đó như ${x?nosuchthing} và bạn di chuột qua nó, thông báo lỗi được hiển thị sẽ cho biết phiên bản FreeMarker nào sử dụng. Nó phải là 2.3.25-incubating. - ddekany
lạ, tôi chỉ thử trong Mac và không thể tái tạo vấn đề. Vấn đề dường như chỉ với vm của tôi. Tôi sẽ có một cái nhìn về phiên bản jar. Tuy nhiên, nó chỉ là một lỗi trong trình soạn thảo, nhưng mã đã được thi hành một cách chính xác. - harshavmb


Nếu sử dụng BeansWrapper với mức phơi sáng Expose.SAFE hoặc Expose.ALL, thì cách tiếp cận Java chuẩn của việc lặp lại tập hợp mục nhập có thể được sử dụng:

Ví dụ: phần sau sẽ hoạt động trong Freemarker (từ ít nhất là phiên bản 2.3.19):

<#list map.entrySet() as entry>  
  <input type="hidden" name="${entry.key}" value="${entry.value}" />
</#list>

Ví dụ, trong Struts2, một phần mở rộng của BeanWrapper được sử dụng với mức phơi sáng được mặc định để cho phép cách lặp này.


12
2018-05-07 14:48



Bạn đã thực sự thử điều này chưa? Bởi vì tôi có một InvalidReferenceException khi tôi thử nó, trong khi map?keys đã làm việc. - kdgregory
Điều này chỉ hoạt động khi sử dụng freemarker.ext.beans.BeansWrapper là trình bao bọc đối tượng. Nếu không thì Maps sẽ tự động được bao bọc thành một SimpleHash đối tượng không hỗ trợ #entrySet(). (xem freemarker.sourceforge.net/docs/api/freemarker/template/…) - Koraktor
Bạn đúng, và tôi đã cập nhật câu trả lời của tôi để phản ánh nhận xét của bạn. Tốt nhìn ra! - rees
Ở trên sẽ không làm việc tốt cho băm được tạo bên trong FTL đặc biệt nếu bạn đang sử dụng trình giải quyết Spring Freemarker với BeanWrapper. Hàm băm được khai báo bên trong tệp Ftl không được bao bọc và sẽ vẫn chỉ là một băm lặp có thể sử dụng các khóa? - skipy
Không sử dụng tinh khiết BeansWrapper, ít nhất là không có mặc định, simpleMapWrapper Là false. Nó rất khó hiểu, vì nó trộn lẫn các khóa với các tên phương thức. Nếu bạn cần gọi entrySet(), chỉ cần tiếp tục sử dụng trình bao bọc đối tượng "sạch", như trình bao bọc mặc định và viết map?api.entrySet() nếu bạn cần truy cập vào Java API thay vì các khóa. - ddekany


Lặp lại các đối tượng

Nếu các khóa bản đồ của bạn là một đối tượng và không phải là một chuỗi, bạn có thể lặp lại nó bằng cách sử dụng Freemarker.

1) Chuyển đổi bản đồ thành danh sách trong bộ điều khiển:

List<Map.Entry<myObjectKey, myObjectValue>> convertedMap  = new ArrayList(originalMap.entrySet());

2) Lặp lại bản đồ trong mẫu Freemarker, truy cập vào đối tượng trong Khóa và đối tượng trong Giá trị:

<#list convertedMap as item>
    <#assign myObjectKey = item.getKey()/>
    <#assign myObjectValue = item.getValue()/>
    [...]
</#list>

2
2018-06-20 08:42





Bạn có thể sử dụng một dấu nháy đơn để truy cập khóa mà bạn đã đặt trong chương trình Java của mình.

Nếu bạn đặt một Bản đồ trong Java như thế này

Map<String,Object> hash = new HashMap<String,Object>();
hash.put("firstname", "a");
hash.put("lastname", "b");

Map<String,Object> map = new HashMap<String,Object>();
map.put("hash", hash);

Sau đó, bạn có thể truy cập các thành viên của 'băm' trong Freemarker như thế này -

${hash['firstname']}
${hash['lastname']}

Đầu ra:

a
b

1
2018-03-19 18:28



cho thấy cách để giải quyết các khóa riêng lẻ, nhưng câu hỏi sẽ hỏi cách lặp lại - Lambart


Để hoàn thành, điều đáng nói là có một bộ sưu tập phong phú về các bộ sưu tập trống trong Freemarker kể từ gần đây.

Cách thuận tiện nhất để lặp lại bản đồ là:

<#list tags>
<ul class="posts">
    <#items as tagName, tagCount>
        <li>{$tagName} (${tagCount})</li>
    </#items>
</ul>
<#else>
    <p>No tags found.</p>
</#list>

Không còn nữa <#if ...> giấy gói.


0
2017-07-23 16:09